Script Repository

RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
A while ago someone on TE mentioned starting a thread as a repository of the scripts we have created that we find useful. At the time I kinda'a thought it would be a cool idea but decided to let someone else start it. But here it goes:
1. Post only scripts you have written.
2. Title your post with the language and purpose.
3. Do not copy someone else's stuff!

I'm sure webmaster might have something else to add.
Here is my first offering. I love the ability in Linux to pipe the ping out put to ^G and get an audible response when the host comes back. How many times have I had to reboot a server and then do a ping -t waiting for it to comeback. I continue working, an waite for the reply. Now I can here the reply... I know it could be less verbose. But I like to keep my code wordy for learning purposes.
#Used to continuously ping a host and get an audible alert when it is back up.
function ContinuousPing-Beep
{
    param([string]$computer)
    $ping = new-object System.Net.NetworkInformation.Ping
    $result = $ping.Send($computer);
    if($result.Status -eq "Success")
    {
        Write-Host "Reply received from $computer" -Foreground green
        Write-Host `a;
    }
    else
    {
        do{$result = $ping.Send($computer);Write-Host "Reply from $computer. Destionation host unreachable." -Foreground red}
            until($result.Status -eq "Success")
            Write-Host "Reply received from $computer" -Foreground green
            Write-Host `a;
    }
}
function ContinuousPing-Voice
{
    param([string]$computer)
 
    $voice = new-object -com SAPI.SpVoice
    $ping = new-object System.Net.NetworkInformation.Ping
    $result = $ping.Send($computer);
    if($result.Status -eq "Success")
    {
        $voice.Speak("Reply received from $computer", 1)
    }
    else
    {
        do{$result = $ping.Send($computer);Write-Host "Reply from $computer. Destionation host unreachable." -Foreground red}
          until($result.Status -eq "Success")
 
        $voice.Speak("Reply received from $computer", 1)
    }
}
ContinuousPing-Beep "192.168.1.1"
ContinuousPing-Voice "192.168.1.1"

Elemental SQL: PowerShell Scripts to Continuously Ping a Host and Give an Audible Alert
«1

Comments

  • NightShade03NightShade03 Member Posts: 1,383 ■■■■■■■□□□
    This is a great idea for a thread. We should start a sourceforge project and compile all the scripts there too for storage.
  • Chris:/*Chris:/* Member Posts: 658 ■■■■■■■■□□
    Though a repository would be nice I find forums to be one of the more difficult places to search for scripts. This is just due to the nature in which the information is searched. I recommend coming up with a template post required to have the meta-data of the script filled out. Otherwise posters will be flying blind, an example would be.

    Author Name:
    Year:
    Script Name:
    Script Version:
    Script Language:
    Script Language Version:
    Operating Systems:
    Dependencies:
    Size:
    Special Instructions:
    Usage:
    Dangers:
    Impacts:
    Degrees:
    M.S. Information Security and Assurance
    B.S. Computer Science - Summa Cum Laude
    A.A.S. Electronic Systems Technology
  • undomielundomiel Member Posts: 2,818
    I don't have too many of my more complex scripts around so I'll just lead off with a simple one. Here's something I came up with for mass creation of users in Exchange. Scripted in PowerShell of course.
    # Display help and exit
    if (($args[0] -eq "-?") -or ($args[0] -eq "-help")) {
      ""
      "Usage: MassCreateUsers.ps1"
      "  Create users specified in Usermailboxes.csv stored in My Documents."
      "  Users are added by default to Sample Group 1 and Sample Group 2."
      ""
      "Usermailboxes.csv format"
      "Firstname, Lastname, alias"
      ""
      "Example: "
      "John, Johnson, j.johnson"
      ""
      exit
    }
    
    # Main loop to create users and add to default groups
    Import-CSV "C:\Documents and Settings\Administrator\My Documents\usermailboxes.csv" |
    foreach {
    $userprincipalname = $_.Firstname + "." + $_.Lastname + "@domain.com"
    $emailAddress = $_.alias + "@domain.com"
    $secureString = ConvertTo-SecureString "PASSWORD!!!" -asPlainText -Force
    $name = $_.Firstname + " " + $_.Lastname
    new-mailbox -name $name -alias $_.alias -FirstName $_.Firstname -LastName $_.Lastname -userPrincipalName  $userprincipalname -database "exchange\Mailbox Database" -OrganizationalUnit "domain.local/OU/Users" -Password $secureString
    Add-DistributionGroupMember -identity "Sample Group 1" -Member $emailAddress
    Add-DistributionGroupMember -identity "Sample Group 2" -Member $emailAddress
    }
    
    Jumping on the IT blogging band wagon -- http://www.jefferyland.com/
  • DevilWAHDevilWAH Member Posts: 2,997 ■■■■■■■■□□
    why not add a ftp site. with scripts orted in to folders via language. if the as some one suggests there is a template headder to all scripts. then scripts could be easly sorted and an index page updated.
    • If you can't explain it simply, you don't understand it well enough. Albert Einstein
    • An arrow can only be shot by pulling it backward. So when life is dragging you back with difficulties. It means that its going to launch you into something great. So just focus and keep aiming.
  • PashPash Member Posts: 1,600 ■■■■■□□□□□
    #Powershell script to perform basic auditing on desktop/servers using WMI
    
    $ErrorActionPreference = "SilentlyContinue"
    
    #### Spreadsheet Location
    $strPath = "C:\Scripts\SERVERINFO\serverinfo.xls"
    
    $onerror = "SilentlyContinue"
    $a = New-Object -comobject Excel.Application
    $a.Visible = $True
    
    $b = $a.Workbooks.Add()
    $c = $b.Worksheets.Item(1)
    
    $c.Cells.Item(1,1) = "Machine Name"
    $c.Cells.Item(1,2) = "OS Running"
    $c.Cells.Item(1,3) = "Domain Role"
    $c.Cells.Item(1,4) = "Total Physical Memory"
    $c.Cells.Item(1,5) = "Total Free Physical Memory"
    $c.Cells.Item(1,6) = "Total Virtual Memory"
    $c.Cells.Item(1,7) = "Total Free Virtual Memory"
    $c.Cells.Item(1,[IMG]https://us.v-cdn.net/6030959/uploads/images/smilies/icon_cool.gif[/IMG] = "Last Boot Time"
    $c.Cells.Item(1,9) = "Bios Version"
    $c.Cells.Item(1,10) = "CPU Info"
    $c.Cells.Item(1,11) = "Disk Info"
    
    $d = $c.UsedRange
    $d.Interior.ColorIndex = 19
    $d.Font.ColorIndex = 11
    $d.Font.Bold = $True
    $d.EntireColumn.AutoFit()
    
    $intRow = 2
    $cred = Get-Credential
    ### For Use Later with Quest AD Cmdlets installed
    ### get-QADcomputer | format-table -hidetableheaders -property Name >> C:\Scripts\computers.txt
    $computers = Get-Content "C:\scripts\computers.txt"
    
    
    foreach ($computer in $computers)
    {
    #### Set Variables
    $user = $env:USERNAME
    
    #### Win32 class short name assignment - add -credential $cred where needed
    TRY {
    $OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer
    $Bios = Get-WmiObject -Class Win32_BIOS -ComputerName $computer 
    $CS = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computer 
    $CPU = Get-WmiObject -Class Win32_Processor -ComputerName $computer 
    $drives = Get-WmiObject -ComputerName $computer Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}
    
    
    
    #### Set Variable information with short name
    $OSRunning = $OS.caption + " " + $OS.OSArchitecture + " SP " + $OS.ServicePackMajorVersion 
    $DomainRole = $CS.DomainRole
    $TotalAvailMemory = $OS.totalvisiblememorysize/1kb 
    $TotalVirtualMemory = $OS.totalvirtualmemorysize/1kb
    $TotalFreeMemory = $OS.FreePhysicalMemory/1kb
    $TotalFreeVirtualMemory = $OS.FreeVirtualMemory/1kb
    $TotalMem = "{0:N2}" -f $TotalAvailMemory
    $TotalVirt = "{0:N2}" -f $TotalVirtualMemory
    $FreeMem = "{0:N2}" -f $TotalFreeMemory
    $FreeVirtMem = "{0:N2}" -f $TotalFreeVirtualMemory
    $date = Get-Date 
    $uptime = $OS.ConvertToDateTime($OS.lastbootuptime)
    $BiosVersion = $Bios.Manufacturer + " " + $Bios.SMBIOSBIOSVERSION + " " + $Bios.ConvertToDateTime($Bios.Releasedate)
    $CPUInfo = $CPU.Name + " & has " + $CPU.NumberOfCores + " Cores & the FSB is " + $CPU.ExtClock + " Mhz"
    $CPULOAD = $CPU.LoadPercentage
    if (($DomainRole -eq "0") -or ($DomainRole -eq "1"))
    {
    $Role = "Work Station"
    }
    elseif (($DomainRole -eq "2") -or ($DomainRole -eq "3"))
    {
    $Role = "Member Server"
    }
    elseif (($DomainRole -eq "4") -or ($DomainRole -eq "5"))
    {
    $Role = "Domain Controller"
    }
    else
    {
    $Role = "Unknown"
    }
    }
    CATCH
    {
    $pcnotfound = "true"
    }
    #### Pump Data to Excel
    if ($pcnotfound -eq "true")
    {
    $c.Cells.Item($intRow, 1) = "PC Not Found"
    }
    else
    {
    $c.Cells.Item($intRow, 1) = $computer
    $c.Cells.Item($intRow, 2) = $OSRunning
    $c.Cells.Item($intRow, 3) = $Role
    $c.Cells.Item($intRow, 4) = "$TotalMem MB"
    $c.Cells.Item($intRow, 5) = "$FreeMem MB"
    $c.Cells.Item($intRow, 6) = "$TotalVirt MB"
    $c.Cells.Item($intRow, 7) = "$FreeVirtMem MB"
    $c.Cells.Item($intRow, [IMG]https://us.v-cdn.net/6030959/uploads/images/smilies/icon_cool.gif[/IMG] = $uptime
    $c.Cells.Item($intRow, 9) = $BiosVersion
    $c.Cells.Item($intRow, 10) = $CPUInfo
    
    $driveStr = ""
    foreach($drive in $drives)
    {
    $size1 = $drive.size / 1GB
    $size = "{0:N2}" -f $size1
    $free1 = $drive.freespace / 1GB
    $free = "{0:N2}" -f $free1
    $freea = $free1 / $size1 * 100
    $freeb = "{0:N2}" -f $freea
    $ID = $drive.DeviceID
    $driveStr += "$ID = Total Space: $size GB / Free Space: $free GB / Free (Percent): $freeb % ` " 
    }
    $c.Cells.Item($intRow, 11) = $driveStr
    }
    
    $d.EntireColumn.AutoFit()
    
    $intRow = $intRow + 1
    $pcnotfound = "false"
    }
    
    IF(Test-Path $strPath)
    {
    Remove-Item $strPath
    $a.ActiveWorkbook.SaveAs($strPath)
    }
    ELSE
    {
    $a.ActiveWorkbook.SaveAs($strPath)
    }
    
    

    Old Script that I use at work frequently. Not in a function, can easily be put into one though...

    Good thread Rob, lets hope this can go further. I think people may end up with rather large profile files after this icon_wink.gif
    DevOps Engineer and Security Champion. https://blog.pash.by - I am trying to find my writing style, so please bear with me.
  • PashPash Member Posts: 1,600 ■■■■■□□□□□
    Just small note for Rob's script. If you running this from a profile loaded into shell probably best to include:-

    $ErrorActionPreference = "SilentlyContinue"

    Otherwise your shell will be spammed with errors.


    Probably quite obvious, but still.
    DevOps Engineer and Security Champion. https://blog.pash.by - I am trying to find my writing style, so please bear with me.
  • it_consultantit_consultant Member Posts: 1,903
    undomiel wrote: »
    I don't have too many of my more complex scripts around so I'll just lead off with a simple one. Here's something I came up with for mass creation of users in Exchange. Scripted in PowerShell of course.
    # Display help and exit
    if (($args[0] -eq "-?") -or ($args[0] -eq "-help")) {
      ""
      "Usage: MassCreateUsers.ps1"
      "  Create users specified in Usermailboxes.csv stored in My Documents."
      "  Users are added by default to Sample Group 1 and Sample Group 2."
      ""
      "Usermailboxes.csv format"
      "Firstname, Lastname, alias"
      ""
      "Example: "
      "John, Johnson, j.johnson"
      ""
      exit
    }
    
    # Main loop to create users and add to default groups
    Import-CSV "C:\Documents and Settings\Administrator\My Documents\usermailboxes.csv" |
    foreach {
    $userprincipalname = $_.Firstname + "." + $_.Lastname + "@domain.com"
    $emailAddress = $_.alias + "@domain.com"
    $secureString = ConvertTo-SecureString "PASSWORD!!!" -asPlainText -Force
    $name = $_.Firstname + " " + $_.Lastname
    new-mailbox -name $name -alias $_.alias -FirstName $_.Firstname -LastName $_.Lastname -userPrincipalName  $userprincipalname -database "exchange\Mailbox Database" -OrganizationalUnit "domain.local/OU/Users" -Password $secureString
    Add-DistributionGroupMember -identity "Sample Group 1" -Member $emailAddress
    Add-DistributionGroupMember -identity "Sample Group 2" -Member $emailAddress
    }
    

    This could be very helpful to me, could you post a generic sample of the csv file you use this with?
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    Pash wrote: »
    Just small note for Rob's script. If you running this from a profile loaded into shell probably best to include:-

    $ErrorActionPreference = "SilentlyContinue"

    Otherwise your shell will be spammed with errors.


    Probably quite obvious, but still.

    What errors are you getting, Pash? I've run it on several machines now with no issue.
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    DevilWAH wrote: »
    why not add a ftp site. with scripts orted in to folders via language. if the as some one suggests there is a template headder to all scripts. then scripts could be easly sorted and an index page updated.

    I'm working on something for this... Just give me a week or two.
  • PashPash Member Posts: 1,600 ■■■■■□□□□□
    What errors are you getting, Pash? I've run it on several machines now with no issue.


    Sure:-

    Exception calling "Send" with "1" argument(s): "An exception occurred during a Ping request."
    At C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1:64 char:26
    + $result = $ping.Send <<<< ($computer);
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    This is if the pc is not available only.
    DevOps Engineer and Security Champion. https://blog.pash.by - I am trying to find my writing style, so please bear with me.
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    DevilWAH wrote: »
    why not add a ftp site. with scripts orted in to folders via language. if the as some one suggests there is a template headder to all scripts. then scripts could be easly sorted and an index page updated.

    PowerShell Junkie

    I'm working on the site. It's in Silverlight, of course, I just put up a quick little page. I'll set up the FTP and organize the directory structure tomorrow.
  • Forsaken_GAForsaken_GA Member Posts: 4,024
    Hrm, wonder if Webmaster would be willing to setup an SVN or CVS repo for this
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    Hrm, wonder if Webmaster would be willing to setup an SVN or CVS repo for this

    With as disorganized as we are as a group, that might be a bit over-kill. I looked at some free ones out on the Interwebs, but they offered no more than a user or two... Of course something like Subversion is fairly easy to set up. I just see it as a management nightmare.
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    Author Name: Bob Kaucher
    Year: 2010
    Script Name: GetSqlJobStatus
    Script Version: 1
    Script Language: PowerShell
    Script Language Version: 2
    Operating Systems: N/A
    Dependencies: SQL SMO
    Size:
    Special Instructions: N/A
    Usage: N/A
    Dangers: None known
    Impacts: None

    I'm still working on the site. I'm still trying to workout if there is anonymous FTP access. If I create account it automatically had read/write access... So I'm still working out the details. Here is one I wrote today. Gets the status of the SQL Job by name.

    Used to get the status of a SQL Job. Could easily be ported to a function.

    /SIZE][/FONT][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#008080][FONT=Courier New][SIZE=2][COLOR=#008080][FONT=Courier New][SIZE=2][COLOR=#008080]void[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")
    /FONT][/SIZE][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#008080][FONT=Courier New][SIZE=2][COLOR=#008080][FONT=Courier New][SIZE=2][COLOR=#008080]void[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2[
    System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")

    $server = new-object "Microsoft.SqlServer.Management.Smo.Server" "localhost"
    $job = $server.JobServer.Jobs/SIZE][/FONT][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000]"Test Job"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2
    $now = Get-Date

    do
    {
    Start-Sleep -Seconds 1
    $job | select Name,CurrentRunStatus,LastRunDate
    $job.Refresh()
    }
    while($job.LastRunDate -lt $now)
    $job | select Name,CurrentRunStatus,LastRunDate
  • PashPash Member Posts: 1,600 ■■■■■□□□□□
    Again, more WMI action from Pash. Wrote this in 20 minutes this morning because I have a customer with 20-30 pc's which are running dog slow, we aren't sure of their memory configurations....well we are now!

    Author Name: Pash
    Year: 2010
    Script Name: GetMemInfo
    Script Version: 1
    Script Language: PowerShell
    Script Language Version: 1/2
    Operating Systems: N/A
    Dependencies: WMI
    Size:
    Special Instructions: N/A
    Usage: N/A
    Dangers: None known
    Impacts: None

    function GetMemInfo ($Computer)
    
    {
    $strpath = "C:\Scripts\$Computer" + ".txt"
    if (Test-Path $strpath)
    {
    Remove-Item $strpath
    }
    Else
    
    {
    Write-Host "File did not exist. Will continue" 
    }
    
    ## Commented out because testing on Local Machine. Add - Credential $cred to the Get-WmiObject if required.
    ## $cred = Get-Credential
    $MemoryInfo = Get-WmiObject -Class Win32_PhysicalMemory -ComputerName $Computer | Where-Object {$_.DeviceLocator -ne "SYSTEM ROM"}
    foreach ($MemoryBank in $MemoryInfo)
    {
    ## Shortname Identifiers for WMI Win32 class properties pulled from PhysicalMemory
    $bankno = $MemoryBank.DeviceLocator
    $formfactor = $MemoryBank.FormFactor
    $memtype = $MemoryBank.MemoryType
    $memspeed = $MemoryBank.Speed
    $mempart = $MemoryBank.PartNumber
    $memserial = $MemoryBank.SerialNumber
    ## Formatting of ugly byte numbers
    $TotalAvailMemory = $MemoryBank.Capacity/1048576
    $TotalMem = "{0:N2}" -f $TotalAvailMemory
    ## switch staement to Identify the Memory Bank Device Locator. Only assuming there is four, but it will still pull out physical bank numbers.
    switch ($bankno)
    {
        XMM1 {Write-Output "---- Memory Bank 1 ----" | Out-File $strpath -Append}
        XMM2 {Write-Output "---- Memory Bank 2 ----" | Out-File $strpath -Append}
        XMM3 {Write-Output "---- Memory Bank 3 ----" | Out-File $strpath -Append}
        XMM4 {Write-Output "---- Memory Bank 4 ----" | Out-File $strpath -Append}
        default {Write-Output "Can't find the memory bank number." | Out-File $strpath -Append}
    }
    ## switch staement to Identify the Memory Bank Device Locator
    switch ($formfactor)
    {
        0 {Write-Output "Form Factor: Unknown" | Out-File $strpath -Append}
        1 {Write-Output "Form Factor: Other" | Out-File $strpath -Append}
        2 {Write-Output "Form Factor: SIP" | Out-File $strpath -Append}
        3 {Write-Output "Form Factor: DIP" | Out-File $strpath -Append}
        4 {Write-Output "Form Factor: ZIP" | Out-File $strpath -Append}
        5 {Write-Output "Form Factor: SOJ" | Out-File $strpath -Append}
        6 {Write-Output "Form Factor: Proprietary" | Out-File $strpath -Append}
        7 {Write-Output "Form Factor: SIMM" | Out-File $strpath -Append}
        8 {Write-Output "Form Factor: DIMM" | Out-File $strpath -Append}
        9 {Write-Output "Form Factor: TSOP" | Out-File $strpath -Append}
        10 {Write-Output "Form Factor: PGA" | Out-File $strpath -Append}
        11 {Write-Output "Form Factor: RIMM" | Out-File $strpath -Append}
        12 {Write-Output "Form Factor: SODIMM" | Out-File $strpath -Append}
        13 {Write-Output "Form Factor: SRIMM" | Out-File $strpath -Append}
        14 {Write-Output "Form Factor: SMD" | Out-File $strpath -Append}
        15 {Write-Output "Form Factor: SSMP" | Out-File $strpath -Append}
        16 {Write-Output "Form Factor: QFP" | Out-File $strpath -Append}
        17 {Write-Output "Form Factor: TQFP" | Out-File $strpath -Append}
        18 {Write-Output "Form Factor: SOIC" | Out-File $strpath -Append}
        19 {Write-Output "Form Factor: LCC" | Out-File $strpath -Append}
        20 {Write-Output "Form Factor: PLCC" | Out-File $strpath -Append}
        21 {Write-Output "Form Factor: BGA" | Out-File $strpath -Append}
        22 {Write-Output "Form Factor: FPBGA" | Out-File $strpath -Append}
        23 {Write-Output "Form Factor: LGA" | Out-File $strpath -Append}
        
        default {Write-Output "Can't find the Form Factor" | Out-File $strpath -Append}
    }
    
    
    ## There are lot's more Memory types but trying to streamline the most obvious desktop types for now (function is getting large)
    switch ($memtype)
    
    {
        20 {Write-Output "Memory Type: DDR" | Out-File $strpath -Append}
        21 {Write-Output "Memory Type: DDR-2" | Out-File $strpath -Append}
        default {Write-Output "Memory Type: Most Likely DDR-3 (Sorry WMI is behind in hardware technology)" | Out-File $strpath -Append}
    
    }
    Write-Output "Memory Size: $TotalMem MB" | Out-File $strpath -Append
    Write-Output "Memory Speed: $memspeed mHz" | Out-File $strpath -Append
    Write-Output "Memory Part No: $mempart" | Out-File $strpath -Append
    Write-Output "Memory Serial No: $memserial `n" | Out-File $strpath -Append
    
    }
    
    }
    
    How is the site coming along Rob? Forget to mention, very good work, my hat is slanted in your direction!
    DevOps Engineer and Security Champion. https://blog.pash.by - I am trying to find my writing style, so please bear with me.
  • DevilWAHDevilWAH Member Posts: 2,997 ■■■■■■■■□□
    I would also suggest that as part of the classifitation people label there scripts Beginner, intermediate and expert.

    For people new to scripting who want to look at examples it can be a bit daunting to open a script with 10,000 lines and no comments.

    just an idea.
    • If you can't explain it simply, you don't understand it well enough. Albert Einstein
    • An arrow can only be shot by pulling it backward. So when life is dragging you back with difficulties. It means that its going to launch you into something great. So just focus and keep aiming.
  • PashPash Member Posts: 1,600 ■■■■■□□□□□
    DevilWAH wrote: »
    I would also suggest that as part of the classifitation people label there scripts Beginner, intermediate and expert.

    For people new to scripting who want to look at examples it can be a bit daunting to open a script with 10,000 lines and no comments.

    just an idea.

    It's hard to classify I think. I mean thing's that become "harder" to read are .net classes not commonly seen etc.

    There are comments there.
    DevOps Engineer and Security Champion. https://blog.pash.by - I am trying to find my writing style, so please bear with me.
  • Chris:/*Chris:/* Member Posts: 658 ■■■■■■■■□□
    Scripts without comments should be banned anyway, trademark of a bad script writer/programmer.
    Degrees:
    M.S. Information Security and Assurance
    B.S. Computer Science - Summa Cum Laude
    A.A.S. Electronic Systems Technology
  • WebmasterWebmaster Admin Posts: 10,292 Admin
    Sorry I missed this topic till now.

    I'd be happy to provide some space on our server for this. I actually prefer to keep content that goes with a thread on TE at TE for several reasons. In general, email me the content (i.e. attachments that can't be added through our attachment feature) and I'll send you back a TE link. For more advanced solutions send me a PM and I'll do my best to accommodate.

    That said, I think just posting them between 'code' or 'php' tags in a single thread/sticky here could work. You can search within a thread so if posters use the initial posting template it should result in a clean topic. We could create two threads, one with the scripts, one for discussing them. Either way is fine by me, we can always adapt and change.
    I'm sure webmaster might have something else to add.
    I do actually, two things:

    - Implied already by being at TE but I think you should clearly determine the scope, the type of scripts you'd like to see (and don't). Maybe even limit the script languages as well (can always expand).

    - Add a disclaimer to the collection or individual scripts (as in use at own risk. TE nor the author of the script is responsible etc etc).
  • MishraMishra Member Posts: 2,468 ■■■■□□□□□□
    I created a script that can push out any files to a machine and execute them on the local machine.

    It's current written purpose was to push a bat file out that installed a patch. But you can edit it to push really anything out to run on the local machine.

    Take a look at it on my blog.

    Cale Pantke
    My blog http://www.calegp.com

    You may learn something!
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    Webmaster wrote: »
    Sorry I missed this topic till now.

    I'd be happy to provide some space on our server for this. I actually prefer to keep content that goes with a thread on TE at TE for several reasons. In general, email me the content (i.e. attachments that can't be added through our attachment feature) and I'll send you back a TE link. For more advanced solutions send me a PM and I'll do my best to accommodate.

    That said, I think just posting them between 'code' or 'php' tags in a single thread/sticky here could work. You can search within a thread so if posters use the initial posting template it should result in a clean topic. We could create two threads, one with the scripts, one for discussing them. Either way is fine by me, we can always adapt and change.

    I do actually, two things:

    - Implied already by being at TE but I think you should clearly determine the scope, the type of scripts you'd like to see (and don't). Maybe even limit the script languages as well (can always expand).

    - Add a disclaimer to the collection or individual scripts (as in use at own risk. TE nor the author of the script is responsible etc etc).

    Totally agree. Have you got anything in mind?
  • WebmasterWebmaster Admin Posts: 10,292 Admin
    I think there are several options, but I'll send you a PM today as it includes some details I don't want to post here yet.
  • DevilWAHDevilWAH Member Posts: 2,997 ■■■■■■■■□□
    A little perl script to output config based on fields from an HTML form.

    See the following thread to see how the from looks, but the basic varibles it provides are

    SWx.name = Switch name
    SWxPy = switch port
    SWxPy.VLAN = VLAN required
    SWxPy.Speed
    SWxPy.Duplex
    SWxPy.ILO
    servername which is used for the description

    the following perl script takes these values and created the CISCO IOS config to configure the ports correctly.
    #!/usr/bin/perl
    # Read the standard input (sent by the form):
    read(STDIN, $FormData, $ENV{'CONTENT_LENGTH'});
    # Get the name and value for each form input:
    @pairs = split(/&/, $FormData);
    # Then for each name/value pair....
    foreach $pair (@pairs){
     # Separate the name and value:
     ($name, $value) = split(/=/, $pair);
     # Convert + signs to spaces:
     $value =~ tr/+/ /;
     # Convert hex pairs (%HH) to ASCII characters:
     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
     # Store values in a hash called %FORM:
     $FORM{$name} = $value;
    }
    print "Content-type: text/html\n\n";
    writeconfig();
     
    sub writeconfig
    {
    # Write the Standard header to Config
    print "<b><u>PORT PROVISIONING IMPLEMENTATION SCRIPT </b></u> <p> \n\n";
    print "<b>Scripted by:</b> $FORM{'username'} on the $FORM{'DateScripted'}</br><b>To be implemented on: </b> $FORM{'Impdate'}<p>";
    print "<b>GCM Refrence:</b>  GSM$FORM{'GCMref'} <b>SRM Refrence:</b>  SRM$FORM{'SRMref'}<p>\n";
    print "<b>CHM refrence:</b>  CHM$FORM{'CHMref'}<p>\n\n";
    print "<b> Data Center: </b> $FORM{'DataCenter'}<b> Hall:</b> $FORM{'Hall'} <b>Rack:</b> $FORM{'Rack'}</br></br>\n\n";
    print "<b>For Server:</b> $FORM{'servername'} <b>in secure server farm:</b> $FORM{'SFF'}<p>";
    print "=======================================================================================================\n=======================================================================================================<p>";
    ## write indivual show commands for ports, use before making change to check what status the ports are showing, 
    $sw=1; # set up the counter for the switch loop, currently two switchs are configured on the form providing the data
    print "You can use the following show commands to display details for indivual ports.<p>";
    while ($sw <= 2)  #start the loop will cycle through twice 
     {
       $switchN="SW" . $sw . "name";
       if ($FORM{$switchN}) #checks if the switch has been filled in (required)
        {
          print "<b>On Switch $FORM{$switchN} use: </b><br><br>";
        }
       $sp=1; #set up the port variable, currently up to 3 ports per switch can be completed on the form so will cycel through 3 times.
       while ($sp <= 3) 
        {
         $swp = "SW" . $sw . "P" . $sp;
             if ($FORM{$swp}) #checks if the port details have been filled in, if so output, if not skip
              {
               print "sh int $FORM{$swp} status <br>\n";
              }
         $sp ++;
        }
        print "<br>";
       $sw ++;
     }
    print "<p>=======================================================================================================<p>";
     
    ## now we can print out the actuly config, using same steps as above to populate the varibles, we can use specifice text along with the varibles to produce the output.
    $sw=1;
    while ($sw <= 2)
     {
        ## Checks if a switch has been filled in and if so starts to write the config
        $switchN="SW" . $sw . "name";
        if ($FORM{$switchN})
       {
         print "<b>Log on to Switch:</b> $FORM{$switchN}<p>\n";
         print "conf t <br><br>";
        ## Next check each port in turn to  see if it has been completed if so create varible and write script
         $sp=1;
         while ($sp <= 3)
           {
          $swp = "SW" . $sw . "P" . $sp;
             if ($FORM{$swp})
         {
                  print "<p>int $FORM{$swp}<br>\n";
              print "description $FORM{servername}";
                  $swpilo = "$swp" . "ilo";
              if ($FORM{$swpilo}) #ilo are not always required on a port, so we need a further check to find out if they are needed before we print them. 
                 {
                   print "$FORM{$swpilo}\n";
                     }
              print "<br>switchport access vlan $FORM{$swp.VLAN}<br>\n";
              print "Speed $FORM{$swp.Speed}<br>\n";
              print "Duplex $FORM{$swp.Duplex}<br>exit\n";
                 }
             $sp ++;
           }
         print "<br> exit <p> show int status<p> wr mem <p>";
         print "=======================================================================================================<p>";
       }
       $sw ++;
     }
    }
    

    The output is will be as below
    [B][U][FONT=Times New Roman]PORT PROVISIONING IMPLEMENTATION SCRIPT [/FONT][/U][/B]
    [B][FONT=Times New Roman]Scripted by:[/FONT][/B][FONT=Times New Roman] DevilWAH on the 27/01/2011[/FONT]
    [FONT=Times New Roman][B]To be implemented on: [/B]29/01/2011 [/FONT]
    [B][FONT=Times New Roman]GCM Refrence:[/FONT][/B][FONT=Times New Roman] GSM002365 [B]SRM Refrence:[/B] SRM003659:021 [/FONT]
    [B][FONT=Times New Roman]CHM refrence:[/FONT][/B][FONT=Times New Roman] CHM0000954874 [/FONT]
    [B][FONT=Times New Roman]Data Center: [/FONT][/B][FONT=Times New Roman]London[B] Hall:[/B] 452 [B]Rack:[/B] B34[/FONT]
     
    [FONT=Times New Roman][B]For Server:[/B] mailpub [B]in secure server farm:[/B] N/A [/FONT]
    [FONT=Times New Roman]======================================================================================================= ======================================================================================================= [/FONT]
    [FONT=Times New Roman]You can use the following show commands to display details for indivual ports. [/FONT]
    [B][FONT=Times New Roman]On Switch lon452sa34 use [/FONT][/B]
     
    [FONT=Times New Roman]sh int g0/3 status [/FONT]
    [FONT=Times New Roman]sh int g0/4 status [/FONT]
    [FONT=Times New Roman]sh int g0/5 status [/FONT]
     
    [FONT=Times New Roman][B]On Switch lon452sa35 use [/B][/FONT]
     
    [FONT=Times New Roman]sh int g0/3 status [/FONT]
    [FONT=Times New Roman]sh int g0/4 status [/FONT]
    [FONT=Times New Roman]======================================================================================================= [/FONT]
    [B][FONT=Times New Roman]Log on to Switch:[/FONT][/B][FONT=Times New Roman] lon452sa34 [/FONT]
    [FONT=Times New Roman]conf t [/FONT]
    [FONT=Times New Roman]int g0/3[/FONT]
    [FONT=Times New Roman]description mailpub[/FONT]
    [FONT=Times New Roman]switchport access vlan 45[/FONT]
    [FONT=Times New Roman]Speed Auto[/FONT]
    [FONT=Times New Roman]Duplex Auto[/FONT]
    [FONT=Times New Roman]exit [/FONT]
    [FONT=Times New Roman]int g0/4[/FONT]
    [FONT=Times New Roman]description mailpub[/FONT]
    [FONT=Times New Roman]switchport access vlan 50[/FONT]
    [FONT=Times New Roman]Speed Auto[/FONT]
    [FONT=Times New Roman]Duplex Auto[/FONT]
    [FONT=Times New Roman]exit [/FONT]
    [FONT=Times New Roman]int g0/5[/FONT]
    [FONT=Times New Roman]description mailpub_ilo [/FONT]
    [FONT=Times New Roman]switchport access vlan 150[/FONT]
    [FONT=Times New Roman]Speed 100[/FONT]
    [FONT=Times New Roman]Duplex Full[/FONT]
    [FONT=Times New Roman]exit [/FONT]
    [FONT=Times New Roman]exit [/FONT]
     
    [FONT=Times New Roman]wr mem [/FONT]
    [FONT=Times New Roman]======================================================================================================= [/FONT]
    [B][FONT=Times New Roman]Log on to Switch:[/FONT][/B][FONT=Times New Roman] lon452sa35 [/FONT]
    [FONT=Times New Roman]conf t [/FONT]
    [FONT=Times New Roman]int g0/3[/FONT]
    [FONT=Times New Roman]description mailpub[/FONT]
    [FONT=Times New Roman]switchport access vlan 46[/FONT]
    [FONT=Times New Roman]Speed Auto[/FONT]
    [FONT=Times New Roman]Duplex Auto[/FONT]
    [FONT=Times New Roman]exit [/FONT]
    [FONT=Times New Roman]int g0/4[/FONT]
    [FONT=Times New Roman]description mailpub[/FONT]
    [FONT=Times New Roman]switchport access vlan 51[/FONT]
    [FONT=Times New Roman]Speed Auto[/FONT]
    [FONT=Times New Roman]Duplex Auto[/FONT]
    [FONT=Times New Roman]exit [/FONT]
    [FONT=Times New Roman]exit [/FONT]
     
    [FONT=Times New Roman]wr mem [/FONT]
    [FONT=Times New Roman]=======================================================================================================[/FONT]
    

    The next step I need to do is and in a second routine to create CATOS code, whicch the use can chose with a check box on the form.

    simple script but nice introduction to perl for me.
    • If you can't explain it simply, you don't understand it well enough. Albert Einstein
    • An arrow can only be shot by pulling it backward. So when life is dragging you back with difficulties. It means that its going to launch you into something great. So just focus and keep aiming.
  • DevilWAHDevilWAH Member Posts: 2,997 ■■■■■■■■□□
    Just a little bit of perl script came across, I don't remember exactly where i came across it, but found it very usefull
    #!/usr/bin/perl
        local ($buffer, @pairs, $pair, $name, $value, %FORM);
        # Read in text
        $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
        if ($ENV{'REQUEST_METHOD'} eq "POST")
        {
            read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
        }else {
            $buffer = $ENV{'QUERY_STRING'};
        }
        # Split information into name/value pairs
        @pairs = split(/&/, $buffer);
        foreach $pair (@pairs)
        {
            ($name, $value) = split(/=/, $pair);
            $value =~ tr/+/ /;
            $value =~ s/%(..)/pack("C", hex($1))/eg;
            $FORM{$name} = $value;
        }
        $text_content = $FORM{scripttext};
     
    # HTTP Header
    print "Content-Type:application/octet-stream; name=\"$FORM{fname}\"\r\n";
    print "Content-Disposition: attachment; filename=\"$FORM{fname}\"\r\n\n";
     
    print "$text_content"; # Actual File Content will go hear.
     
    open( FILE, "<$FORM{fname}" );
    while(read(FILE, $buffer, 100) )
    {
       print("$buffer");
    }
    

    The first part is standard for processing values passed in a script. In this case two values are passed

    $fname: which is in the in the form of <date>-<refrence>.txt in my case, and will form the file name to be downloded

    and $text_content: whihc is the raw text that will form the content of the down load its self.

    calling this script form a form, and pass the two values, and a download pop up will apear with the chosen filename.

    devilWAH
    • If you can't explain it simply, you don't understand it well enough. Albert Einstein
    • An arrow can only be shot by pulling it backward. So when life is dragging you back with difficulties. It means that its going to launch you into something great. So just focus and keep aiming.
  • undomielundomiel Member Posts: 2,818
    Here's a little powershell script I put together to end the monotony of creating a whole slew of SonicWall vpns. Nothing fancy but none of mine usually are. It imports a list of locations, WAN addresses, and LAN addresses from a CSV. You'll want to customize some of the lines to your own config of course as it doesn't pull every single detail from the CSV i.e. for the local networks it uses a pre-created object of VPN Subnets.
    # Display help and exit
    if (($args[0] -eq "-?") -or ($args[0] -eq "-help"))
    {
      ""
      "Usage: BuildVpnScript.ps1"
      "  Writes out the script for a SonicWall Enhanced OS to build VPNs,"
      "  and appends it to the output file."
      "  Input is via a CSV."
      ""
      "Syntax: BuildVpnScript.ps1 OutputScriptPath InputCSVPath"
      ""
      "CSV Format:"
      "  Location,WAN,Network,Key"
      ""
    
      exit
    }
    
    if (($args[0] -eq $NULL) -or ($args[1] -eq $NULL))
    {
      "Please supply the command line, usage -help for usage"
      exit
    }
    
    # Wrapper for out-file to simplify data input
    # note that it appends to the file
    function Out-FileWrapper($InData)
    {
      out-file -filepath $outpath -append -inputobject $InData
    }
    
    # Imports the CSV and sets the output path
    $sitelists = import-csv -path $args[1]
    $outpath = $args[0]
    
    write-host "Beginning processing ..."
    # Main loop that outputs the script
    # It skips any lines that have a blank Location
    foreach($entry in $sitelists)
    {
      if($entry.Location -ne "")
      {
        Out-FileWrapper -InData "address-object `"$($entry.Location)`""
        $scriptbuilder = "network " + $entry.Network + " 255.255.255.0"
        Out-FileWrapper -InData "network $($entry.Network) 255.255.255.0"
        Out-FileWrapper -InData "exit"
        Out-FileWrapper -InData "vpn policy `"$($entry.Location)`" pre-shared"
        Out-FileWrapper -InData "gw ip-address $($entry.WAN)"
        Out-FileWrapper -InData "network local address-object `"VPN Subnets`""
        Out-FileWrapper -InData "network remote address-object `"$($entry.Location)`""
        Out-FileWrapper -InData "proposal ike main encr aes-128 auth sha1 dh 2 lifetime 28800"
        Out-FileWrapper -InData "proposal ipsec esp encr aes-128 auth sha1 dh 2 lifetime 28800"
        Out-FileWrapper -InData "pre-shared-secret `"$($entry.Key)`""
        Out-FileWrapper -InData "exit"
      }
    }
    write-host "Processing complete, saved to $outpath"
    
    Jumping on the IT blogging band wagon -- http://www.jefferyland.com/
  • DevilWAHDevilWAH Member Posts: 2,997 ■■■■■■■■□□
    www.devilwah.com/switch.shtml

    If any one wants to see the code i posted below in action
    • If you can't explain it simply, you don't understand it well enough. Albert Einstein
    • An arrow can only be shot by pulling it backward. So when life is dragging you back with difficulties. It means that its going to launch you into something great. So just focus and keep aiming.
  • hasitha257hasitha257 Member Posts: 25 ■□□□□□□□□□
    Guyz, Scripting is one of those gray areas for me . Quwestion for you all : When you have a script ( any script) , how do i launch those scripts from any shell

    p.s : I am not even sure if my question makes sense but basically i want to know how i can kickoff a script .icon_sad.gif
  • RobertKaucherRobertKaucher Member Posts: 4,299 ■■■■■■■■■■
    hasitha257 wrote: »
    Guyz, Scripting is one of those gray areas for me . Quwestion for you all : When you have a script ( any script) , how do i launch those scripts from any shell

    p.s : I am not even sure if my question makes sense but basically i want to know how i can kickoff a script .icon_sad.gif

    It kind of depends. But usually you just type the path/name of the script in Windows (ie via CMD or PowerShell console). There are many exceptions to this, though. Do you have anything specific in mind?
  • hasitha257hasitha257 Member Posts: 25 ■□□□□□□□□□
    It kind of depends. But usually you just type the path/name of the script in Windows (ie via CMD or PowerShell console). There are many exceptions to this, though. Do you have anything specific in mind?


    I am intersted to know how to kickoff from shell promt ( ksh)
  • undomielundomiel Member Posts: 2,818
    Here's a script that will most likely be useless for anything but poking at and learning. I have a hyper-v cluster that I manage that has virtual machines that randomly disable their nic until they're either rebooted or live migrated ever since installing SP1 for 2008 R2. Until a resolution is found I've written this script to keep the machines running whenever they lose their connection. It pings the machines and will live migrate a machine if it does not respond to a ping. It also writes an event to the event log so that you can more closely pinpoint when the failure occurred.
    # This script will check all of the virtual machines listed in your CSV
    # whether they are responding to a ping or not.
    # If they are not then the script will Live Migrate the machine to the
    # other node in your cluster. This script does some basic checking on
    # whether the machine is in a state to migrate or not. Please note that
    # this script does not scale well as it was designed around a two node
    # cluster.
    #
    # This script is written as a poor man's monitoring, designed to be run
    # as a scheduled task. Please test properly before putting into
    # production.
    #
    # Script is run like so:
    # MachineMonitor.ps1 C:\machinelist.csv hypervcluster
    #
    # CSV format is like so:
    # Name,Group,Address,HostName
    #
    # Name = VM cluster resource name, what you see in Get-ClusterResource
    # Group = VM cluster group name, what you see in Get-ClusterGroup
    # Address = ip address for your machine
    # HostName = Hyper-V name that you see in the Hyper-V Manager
    #
    
    Import-Module FailoverClusters
    
    function Start-VM($SourceVM)
    {
      Write-Host $SourceVM "is offline, starting the VM now."
      Start-ClusterResource -Cluster $clustername -Name "$SourceVM"
    }
    
    # Migrate VM to first available node
    function Migrate-VM($SourceVM, $SourceGroup, $SourceName)
    {
      Write-Host $SourceName "is online but not responding to pings, commencing live migration."
      $vmmigration = Get-ClusterResource -Cluster $clustername -Name "$SourceVM" | Get-ClusterParameter MigrationState
    
      # Checking the current migration state
      # 0 means not migrating and 5 is that it failed the previous migration attempt
      if($vmmigration.Value -eq 0 -or $vmmigration.value -eq 5)
      {
        # Get the node to migrate to
        $freenode = Get-FirstAcceptableNode -SourceGroup $SourceGroup -SourceName $SourceName
        if($freenode -eq $false) { return $false }
        else
        {
          $vmnode = Get-ClusterGroup -Cluster $clustername -Name "$SourceGroup"
          Get-ClusterGroup -Cluster $clustername -Name "$SourceGroup" | Move-ClusterVirtualMachineRole -Node $freenode
        }
      }
    }
    
    # This function runs through and checks the nodes for whether they have enough memory to hold the vm
    # It does not take into account anything else about the host node since this is just an emergency
    # procedure after all and not a load balancer
    function Get-FirstAcceptableNode($SourceGroup, $SourceName)
    {
      $OwnerNode = Get-ClusterGroup -Cluster $clustername -Name "$SourceGroup" | select OwnerNode
    
      # Grabs the memory settings from the virtual machine taking into account dynamic memory
    $VM = Get-WmiObject -namespace "root\virtualization" -ComputerName $OwnerNode.OwnerNode -Query "Select Name from Msvm_ComputerSystem Where ElementName='$($SourceName)'"
    $VMSettings = Get-WmiObject -namespace "root\virtualization" -ComputerName $OwnerNode.OwnerNode -Query "Select __PATH from Msvm_VirtualSystemSettingData Where SystemName='$($VM.Name)' AND SettingType=3"
    $VMMemory = Get-WmiObject -Namespace "root\virtualization" -ComputerName $OwnerNode.OwnerNode -Query "Associators of {$($VMSettings.__PATH)} Where AssocClass=Msvm_VirtualSystemSettingDataComponent Role=GroupComponent ResultClass=Msvm_MemorySettingData"
    
    
      $counter = 0
      while($counter -lt $nodes.count)
      {
        # Skip the VM's owner
        if($nodes[$counter] -like $ownernode.OwnerNode)
        {
          # Owner node, skipping
        }
        else
        {
          # Grabs the memory capacity from the node
          $currentnode = Get-WmiObject -Namespace "root\cimv2" -ComputerName $nodes[$counter] -Query "Select FreePhysicalMemory from Win32_Operatingsystem"
          # Reserve some for the host
          $nodefreememory = $currentnode.FreePhysicalMemory / 1024 - 512
    
          if($VMMemory.Reservation -gt $nodefreememory)
          { 
            Write-Host "Node doesn't have enough memory"
          }
          else
          { 
            Write-Host "Node is available for Live Migration."
    	Write-Host "Migrating to node" $nodes[$counter]
            return $nodes[$counter]
          }
        }
        $counter++
      }
      Write-Host "Could not find an acceptable node"
      return $false
    }
    
    $VMs = Import-CSV -path $args[0]
    $clustername = $args[1]
    
    # Compile a list of nodes currently up in the cluster, nodes that are down are
    # useless to us
    $nodes = Get-ClusterNode -Cluster $clustername | where {$_.State -eq "Up"}
    
    # Loop through each VM in the CSV and ping it
    foreach($VM in $VMs)
    {
      $pingresult = Get-WmiObject -class "Win32_PingStatus" -Filter "Address='$($VM.Address)'"
    
      # If the host does not respond first check its state
      if($pingresult.StatusCode -ne 0)
      {
        Write-Host $VM.HostName "failed ping test, evaluating source machine ..."
        $hostvm = Get-ClusterResource -Cluster $clustername -Name "$($VM.Name)" | Get-ClusterParameter VmState
        Write-EventLog -LogName Application -Source Application -EventID 59000 -EntryType Warning -Message "$($VM.HostName) did not respond to pings and needed to be live migrated to restore connection."
    
        # Now need to check the state of the VM to see if it is turned off
        Write-Host $VM.HostName "state is:  " $hostvm.Value
        switch ($hostvm.Value)
        {
           # It is offline so we need to start the VM
          3 { Start-VM -SourceVM $VM.Name }
    
           # It is online, first check to see if it is migrating
          2 { 
    	  Migrate-VM -SourceVM $VM.Name -SourceGroup $VM.Group -SourceName "$($VM.HostName)"
            }
        }
      }
    }
    
    Jumping on the IT blogging band wagon -- http://www.jefferyland.com/
Sign In or Register to comment.