ConvertTo-EnhancedHTML : Cannot bind argument to parameter 'HTMLFragments'

This topic contains 9 replies, has 2 voices, and was last updated by Profile photo of Ahmet Cardak Ahmet Cardak 9 months, 3 weeks ago.

  • Author
    Posts
  • #34982
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    I am trying to use Don John's Famous Enhanced HTML Report Script to pull some data out of Exchange 2013 Servers, I have created two functions to pull some basic data to test and i got this error message below. When i run the functions by itself they are working fine. I know the HTML requires string, does not like Arrays, Out-string does that but i still get the error below.

    Error Message;
    ConvertTo-EnhancedHTML : Cannot bind argument to parameter 'HTMLFragments' because it is an empty string.
    At C:\Scripts\ExchReport.ps1:144 char:32
    + ConvertTo-EnhancedHTML @params |
    + ~~~~~~~
    + CategoryInfo : InvalidData: (:) [ConvertTo-EnhancedHTML], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,ConvertTo-EnhancedHTML

    ConvertTo-EnhancedHTML : Cannot bind argument to parameter 'HTMLFragments' because it is an empty string.
    At C:\Scripts\ExchReport.ps1:144 char:32
    + ConvertTo-EnhancedHTML @params |
    + ~~~~~~~
    + CategoryInfo : InvalidData: (:) [ConvertTo-EnhancedHTML], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,ConvertTo-EnhancedHTML

    Script;

    #requires -module EnhancedHTML2

    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True)]
    [string[]]$ComputerName,

    [Parameter(Mandatory=$True)]
    [string]$Path
    )
    BEGIN {
    Remove-Module EnhancedHTML2
    Import-Module EnhancedHTML2
    }
    PROCESS {

    $CSS = @"

    body {
    color:#333333;
    font-family:Calibri,Tahoma;
    font-size: 10pt;
    }
    h1 {
    text-align:center;
    }
    h2 {
    border-top:1px solid #666666;
    }

    th {
    font-weight:bold;
    color:#eeeeee;
    background-color:#333333;
    cursor:pointer;
    }
    .odd { background-color:#ffffff; }
    .even { background-color:#dddddd; }
    .paginate_enabled_next, .paginate_enabled_previous {
    cursor:pointer;
    border:1px solid #222222;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px;
    }
    .paginate_disabled_previous, .paginate_disabled_next {
    color:#666666;
    cursor:pointer;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px;
    }
    .dataTables_info { margin-bottom:4px; }
    .sectionheader { cursor:pointer; }
    .sectionheader:hover { color:red; }
    .grid { width:100% }
    .red {
    color:red;
    font-weight:bold;
    }

    "@

    function Get-BootInfo {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $BootInfo = Get-CimInstance -ClassName win32_operatingsystem -ComputerName $ComputerName
    $props = @{'Server'=$bootInfo.CSName;
    'LastBootTime'=$bootInfo.LastBootUpTime}

    New-Object -TypeName PSObject -Property $props
    }

    function Get-LargeEmail {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $email = Get-MailboxStatistics -server $computerName |
    sort-object -Property totalitemsize -des |
    select-object Displayname, ItemCount, totalItemSize -first 10

    $props = @{'User'=$email.Displayname;
    'ItemCount'=$email.ItemCount;
    'Mailbox Size'=$email.totalItemSize;
    }

    New-Object -TypeName PSObject -Property $props
    }

    foreach ($computer in $computername) {
    try {
    $everything_ok = $true
    Write-Verbose "Checking connectivity to $computer"
    Get-WmiObject -class Win32_BIOS -ComputerName $Computer -EA Stop | Out-Null
    } catch {
    Write-Warning "$computer failed"
    $everything_ok = $false
    }

    if ($everything_ok) {
    $filepath = Join-Path -Path $Path -ChildPath "$computer.html"

    $params = @{'As'='Table';
    'PreContent'='Server UP Time'}
    $html_BootInfo = Get-BootInfo -ComputerName $computer |
    Out-String |
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'PreContent'='Largest Email Users'}
    $html_email = Get-LargeEmail -ComputerName $computer |
    Out-String |
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'CssStyleSheet'=$style;
    'Title'="System Report for $computer";
    'PreContent'="System Report for $computer";
    'HTMLFragments'=@($html_BootInf,$html_email);
    'jQueryDataTableUri'='http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.3/jquery.dataTables.min.js';
    'jQueryUri'='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js'}
    ConvertTo-EnhancedHTML @params |
    Out-File -FilePath $filepath

    }
    }

    }

  • #34991
    Profile photo of Don Jones
    Don Jones
    Keymaster

    The problem is here:

    'HTMLFragments'=@($html_BootInf,$html_email);

    Neither of those variables appears to contain anything, according to the error message. Because you didn't format your script as code, or paste it from Gist, it's a little hard to follow, and I'm not able to run your code on my environment.

    But you appear to have a problem here:

    $html_BootInfo = Get-BootInfo -ComputerName $computer |
    Out-String |
    ConvertTo-EnhancedHTMLFragment @params

    That won't work. ConvertTo-EnhancedHTMLFragment wants objects as input, not a string. If you debug your code, I imagine you'll find $html_BootInfo to be empty. You probably meant for Out-String to come after ConvertTo-EnhancedHTMLFragment, as in the examples in the book.

  • #34999
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    Yes you are right, I have moved the Out-String to the end and it worked. Now, i have eveything on the same line instead of Table or List;

    ItemCount

    16565 18306 58478 29877 17408 477289 9941 15478 19461 7913 15.43 GB (16,571,992,221 bytes) 14.92 GB (16,019,366,454 bytes) 10.26 GB (11,020,001,935 bytes) 8.761 GB (9,406,653,181 bytes) 8.465 GB (9,089,731,166 bytes) 7.724 GB (8,293,210,131 bytes) 7.577 GB (8,136,272,688 bytes) 6.931 GB (7,442,630,099 bytes) 6.272 GB (6,735,010,952 bytes) 5.911 GB (6,346,656,429 bytes)

    Names
    Meza, Juan DeBoer, Carol Schmitt, Klaus Theise, Mike Koetje, Chris Snow, Steve Couturier, Dorothy Bahr, Joe Westveld, Belinda Johnson, Tony

  • #35000
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Well, look at what you're doing:

    function Get-LargeEmail {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $email = Get-MailboxStatistics -server $computerName |
    sort-object -Property totalitemsize -des |
    select-object Displayname, ItemCount, totalItemSize -first 10
    
    $props = @{'User'=$email.Displayname;
    'ItemCount'=$email.ItemCount;
    'Mailbox Size'=$email.totalItemSize;
    }
    

    You're retrieving ALL the mailbox statistics from a single server, right? So $email doesn't represent ONE mailbox, it represents them ALL. So $email.ItemCount isn't a single mailbox item count, it is the item counts for ALL mailboxes. So that's what you're showing in your output.

  • #35002
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    So the script is doing exactly what it is told 🙂 how do i change it to show the each one of the items in a table like this;
    Name ItemCount MailboxSize
    Mr Funny Guy 222554 25GB
    MS Funny Girl 665464654 54GB

  • #35006
    Profile photo of Don Jones
    Don Jones
    Keymaster

    You need to get all the mailboxes, but then enumerate (ForEach) through each one. For each one, output a unique object with whatever properties you want. Each object then becomes a table row, and each property is a table column.

  • #35014
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    I have added the ForEach inside the function but now i got this error;

    MyFunction

    function Get-LargeEmail {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $Mailboxes = Get-MailboxStatistics -server $computerName |
    sort-object -Property totalitemsize -des |
    select-object Displayname, ItemCount, totalItemSize -first 10

    foreach($Mailbox in $Mailboxes){

    $props = @{n="Total Items";exp={$Mailbox.ItemCount}},
    @{n="Total Mailbox Size (MB)";exp={$Mailbox.totalitemsize.value.ToMb()}}

    New-Object -TypeName PSObject -Property $props

    ERROR'
    New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter 'Property'. Specified method is not supported.
    At C:\Scripts\ExchReport.ps1:109 char:45
    + New-Object -TypeName PSObject -Property $props
    + ~~~~~~
    + CategoryInfo : InvalidArgument: (:) [New-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand

  • #35016
    Profile photo of Don Jones
    Don Jones
    Keymaster

    That's because your New-Object is outside the ForEach loop, I believe. However, because you're still not formatting your code here, it's difficult to be certain.

  • #35018
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    I got it to work finally, thank you for all your help. No i can add more functions and prepare a complete Exchange 2013 report.

    function Get-LargeEmail {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $Mailboxes = Get-MailboxStatistics -server $computerName |
    Sort-Object -Property totalitemsize -des |
    Select-Object Displayname,Database, TotalDeletedItemSize, ItemCount, TotalItemSize, ID -first 10

    foreach($Mailbox in $Mailboxes){

    $props = @{'Deleted Item Size'=$Mailbox.TotalDeletedItemSize
    'Database'=$Mailbox.Database;
    'User Name ' =$Mailbox.DisplayName;
    'Total Items'=$Mailbox.ItemCount;
    'Total Mailbox Size'=$Mailbox.totalitemsize}

    New-Object -TypeName PSCustomObject -Property $props

  • #35180
    Profile photo of Ahmet Cardak
    Ahmet Cardak
    Participant

    Me again 🙂
    I have 8 Exchange Server, i got all the information I need , i prepared the functions. I want to be able to put all the information on the same page and send it out as email, instead of making 8 attachments.When i run the functions individually they generate the result by Server Name, When I put it in the Script, i only get one server info. I checked the module did not see any parameter for it, what am i missing ?

    Here is the whole Code;

    #requires -module EnhancedHTML2

    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True)]
    [string[]]$ComputerName,

    [Parameter(Mandatory=$True)]
    [string]$Path
    )
    BEGIN {
    Remove-Module EnhancedHTML2
    Import-Module EnhancedHTML2
    }
    PROCESS {

    $CSS = @"

    body {
    color:#333333;
    font-family:Calibri,Tahoma,Arial;
    font-size: 10pt;
    }
    h1 {
    text-align:center;
    }
    h2 {
    border-top:1px solid #666666;
    }

    th {
    font-weight:bold;
    color:#eeeeee;
    background-color:#333333;
    cursor:pointer;
    }
    .odd { background-color:#ffffff; }
    .even { background-color:#dddddd; }
    .paginate_enabled_next, .paginate_enabled_previous {
    cursor:pointer;
    border:1px solid #222222;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px;
    }
    .paginate_disabled_previous, .paginate_disabled_next {
    color:#666666;
    cursor:pointer;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px;
    }
    .dataTables_info { margin-bottom:4px; }
    .sectionheader { cursor:pointer; }
    .sectionheader:hover { color:red; }
    .grid { width:100% }
    .red {
    color:red;
    font-weight:bold;
    }

    "@

    function Get-BootInfo {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string[]]$ComputerName
    )
    $BootInfo = Get-CimInstance -ClassName win32_operatingsystem -ComputerName $ComputerName

    foreach($B in $BootInfo){
    $props = @{'Server'=$B.CSName;
    'LastBootTime'=$B.LastBootUpTime}

    New-Object -TypeName PSObject -Property $props
    }
    }

    function Get-InfoDisk {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string[]]$ComputerName
    )
    $drives = Get-WmiObject -class Win32_LogicalDisk -ComputerName $ComputerName `
    -Filter "DriveType=3"

    foreach ($drive in $drives) {
    $props = @{'Server'=$drive.SystemName
    'Drive'=$drive.DeviceID
    'Size'=$drive.size / 1GB -as [int]
    'Free'="{0:N2}" -f ($drive.freespace / 1GB)
    'FreePct'=$drive.freespace / $drive.size * 100 -as [int]
    }
    New-Object -TypeName PSObject -Property $props
    }
    }

    function Get-LargeEmail {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][string]$ComputerName
    )
    $Mailboxes = Get-MailboxStatistics -server $computerName |
    Sort-Object -Property totalitemsize -des |
    Select-Object Displayname,Database, TotalDeletedItemSize, ItemCount, TotalItemSize, ID -first 30

    foreach($Mailbox in $Mailboxes){

    $props = @{'Deleted Item Size'=$Mailbox.TotalDeletedItemSize
    'Database'=$Mailbox.Database;
    'User Name ' =$Mailbox.DisplayName;
    'Total Items'=$Mailbox.ItemCount;
    'Total Mailbox Size'=$Mailbox.totalitemsize}

    New-Object -TypeName PSCustomObject -Property $props

    }
    }

    function Get-DatabaseStatistics {
    [CmdletBinding()]

    $Databases = Get-MailboxDatabase -Status

    foreach($Database in $Databases) {
    $DBSize = $Database.DatabaseSize
    $MBCount = @(Get-MailboxStatistics -Database $Database.Name).Count

    $MBAvg = Get-MailboxStatistics -Database $Database.Name |
    %{$_.TotalItemSize.value.ToGB()} |
    Measure-Object -Average

    New-Object PSObject -Property @{
    Server = $Database.Server.Name
    'Database Name' = $Database.Name
    'Mailbox Count' = $MBCount
    "DatabaseSize (GB)" = $DBSize.ToGB()
    "AverageMailboxSize (MB)" = $MBAvg.Average
    "WhiteSpace (MB)" = $Database.AvailableNewMailboxSpace.ToMb()
    }
    }
    }

    function Get-TransportQ {
    [CmdletBinding()]

    $Queues = Get-TransportService DETMSEX* | Get-Queue -Filter {MessageCount -gt 10} |
    Sort-Object -Property MessageCount -Des |
    Select-Object Identity,MessageCount,Status,NextHopDomain

    foreach($Queue in $Queues){

    $props = @{'Queue Name'=$Queue.Identity;
    'Status'=$Queue.Status;
    'Mail in Queue'=$Queue.MessageCount;
    'Destination'=$Queue.NextHopDomain;
    }

    New-Object -TypeName PSCustomObject -Property $props

    }
    }

    # Each object is a table row, each property is a table column.

    foreach ($computer in $computername) {
    try {
    $everything_ok = $true
    Write-Verbose "Checking connectivity to $computer"
    Get-WmiObject -class Win32_BIOS -ComputerName $Computer -EA Stop | Out-Null
    } catch {
    Write-Warning "$computer failed"
    $everything_ok = $false
    }

    if ($everything_ok) {
    $filepath = Join-Path -Path $Path -ChildPath "$computer.html"

    $params = @{'As'='Table';
    'PreContent'='Server UP Time';
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeHiddenSection'=$False;
    'TableCssClass'='grid'}
    $html_BootInfo = Get-BootInfo -ComputerName $computer |
    ConvertTo-EnhancedHTMLFragment @params
    $params = @{'As'='Table';
    'PreContent'='♦ Local Disks';
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeHiddenSection'=$false;
    'TableCssClass'='grid';
    'Properties'='Drive',
    @{n='Size(GB)';e={$_.Size}},
    @{n='Free(GB)';e={$_.Free};css={if ($_.FreePct -lt 80) { 'red' }}},
    @{n='Free(%)';e={$_.FreePct};css={if ($_.FreeePct -lt 80) { 'red' }}}}
    $html_dr = Get-InfoDisk -ComputerName $computer |
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'PreContent'='Largest Email Users'
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeHiddenSection'=$True;
    'MakeTableDynamic'=$true;
    'TableCssClass'='grid'}

    $html_email = Get-LargeEmail -ComputerName $computer |
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'PreContent'='Mailbox Database Info'
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeHiddenSection'=$True;
    'MakeTableDynamic'=$true;
    'TableCssClass'='grid'}

    $Databases = Get-DatabaseStatistics $ComputerName|
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'PreContent'='Transport Queues'
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeHiddenSection'=$True;
    'MakeTableDynamic'=$true;
    'TableCssClass'='grid'}

    $Queues = Get-TransportQ |
    ConvertTo-EnhancedHTMLFragment @params

    $params = @{'CssStyleSheet'=$style;
    'Title'="Exchange Server $computer";
    'PreContent'="EXCHANGE ENVIRONMENT REPORT for $computer";
    'HTMLFragments'=@($html_BootInfo,$html_dr,$html_email,$Databases,$Queues);
    'jQueryDataTableUri'='http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.3/jquery.dataTables.min.js';
    'jQueryUri'='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js'}
    ConvertTo-EnhancedHTML @params |
    Out-File -FilePath $filepath

    }
    }

    }

You must be logged in to reply to this topic.