iText7 and Object-Position - powershell

I have created this script:
Function Make-Base64Image
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 28-Oct-2022
Created by: TheStingPilot
Organization:
Functionname: Make-Base64Image
=============================================================================================================================================
.SYNOPSIS
This function removes the given bit from the picture.
Based on:
https://devblogs.microsoft.com/scripting/expert-solution-for-2011-scripting-games-advanced-event-8-use-powershell-to-resize-images-and-to-remove-exif-data/
#>
Param
(
[Parameter(Mandatory=$True)] [System.IO.FileInfo] $SourceFileName,
[Parameter(Mandatory=$False)][Int] $Scale = 100
)
$img = [System.Drawing.Image]::FromFile($SourceFileName)
$ImgFormat = [System.Drawing.Imaging.ImageFormat]::Jpeg
$Size = "$([int]($img.Width*($Scale/100))), $([int]($img.Height*($Scale/100)))"
$img_new = New-Object System.Drawing.Bitmap($img, $Size)
$MemoryStream = New-Object -TypeName System.IO.MemoryStream
$img_new.Save($MemoryStream, $ImgFormat)
$cImgBytes = [Byte[]]($MemoryStream.ToArray())
$sBase64 = [System.Convert]::ToBase64String($cImgBytes)
Return $sBase64
}
$CurrentDir = $(Split-Path $MyInvocation.MyCommand.Definition)
$Picture = "$CurrentDir\WP_20170426_15_19_09_Pro.jpg"
$sBase64 = Make-Base64Image -SourceFileName $Picture -Scale 20
$CSS = #"
<style type="text/css">
.image-wrapper img {
object-fit: contain;
object-position: bottom;
height: 806px;
width: 806px;
}
</style>
"#
$HTML = #"
<html>
<head>
{0}
<title>Test</title>
</head>
<body>
<h1>Test</h1>
<p>Hello World</p>
<div class="image-wrapper"><img alt="Embedded Image" src="data:image/jpeg;base64,{1}" style="transform:rotate(90deg);"></img></div>
</body>
</html>
"#
$HTMLDocument = $HTML -f $CSS, $sBase64
$HTMLOutput = "$CurrentDir\testfile.html"
$HTMLDocument | Out-File -FilePath $HTMLOutput -Force
$DLLFiles = (Get-ChildItem -Path "$CurrentDir\DLLFilesForItext7" -Filter *.dll -File).FullName
ForEach ($DLLFile in $DLLFiles)
{
Add-Type -Path $($DLLFile)
}
$PDFFileToWrite = [System.IO.FileInfo]::new($HTMLOutput.Replace(".html",".pdf"))
$HTMLInputFile = [System.IO.FileInfo]::new($HTMLOutput)
[iText.Html2Pdf.HtmlConverter]::ConvertToPdf($HTMLInputFile,$PDFFileToWrite)
What I see is that the created PDF has the picture not on the left side. If I do not apply the object-position in the CSS the same result can be seen in the created html file. To me, it seems that iText7 does not apply the object-position.
Is there an alternative for this?
What can I do to resolve this issue?
The code plus picture can be found here.
Feedback is appreciated.
With kind regards,
TheStingPilot

Related

Proccessing hashtable values correctly inside a ForEach-Object

I have a .xml file that I want to use to create windows .url files out of:
<?xml version="1.0" encoding="UTF-16" ?>
<items_list>
<item>
<title>About topics - PowerShell | Microsoft Learn</title>
<url>https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about?view=powershell-7.3</url>
</item>
<item>
<title>PowerShell HashTable - Everything you need to know — LazyAdmin</title>
<url>https://lazyadmin.nl/powershell/powershell-hashtable/</url>
</item>
<item>
<title>How a Regex Engine Works Internally</title>
<url>https://www.regular-expressions.info/engine.html</url>
</item>
</items_list>
I placed the Titles and URLs into a Hashtable:
$InXML = [XML](Get-Content .\test.xml)
$BookMarks = [ordered]#{
Title = (Select-Xml -xml $InXML -XPath "//title" | % {$_.Node.InnerXml}) -replace '\?|\\|/|:'
URL = Select-Xml -xml $InXML -XPath "//url" | % {$_.Node.InnerXml}
}
Everything good so far, then I start running into problems when I try to loop through the Titles and URLs:
$wshshell = New-Object -ComObject WScript.Shell
$BookMarks | ForEach-Object {
$Title = $_.Title
$Url = $_.Url
Write-Output $shortcutFilePath
# $shortcutFilePath = Join-Path -path "c:\temp" -ChildPath "$Title.Url"
# $shortcut = $shell.CreateShortcut($shortcutFilePath)
# $shortcut.TargetPath = "$Url"
# $shortcut.Save()
}
I commented out my actuall code in the Loop to see whats actually happening with Write-Output. All the key values get concatenated into one long title or one long .url
What I am expecting is to get a single pair of a Url and Title at a time, so that I can create the .url file in the loop.
Reading the documentations and articles on how to do this. I tried variations of:
$BookMarks.Values | ForEach-Object {
$Title = $_.Title
$Url = $_.Url
Write-Output $Title
Write-Output $Url
}
I keep getting null variables.
Any help or ideas would be really appreciated.
I suggest simplifying and streamlining your code as follows, which bypasses your problem:
[xml] $inXML = Get-Content -Raw .\test.xml
$inXml.items_list.item | ForEach-Object {
$title = $_.Title
$url = $_.Url
"[$title] [$url]" # sample output.
# ... work with $title and $url here
# $wshshell = New-Object -ComObject WScript.Shell
# ...
}
The above uses PowerShell's adaptation of the XML DOM, which allows you to access elements and attributes as if they were properties.

How to consume a click-event in a Toast-Message?

I made a powershell code that shows a toast-message with a "yes/no" option. Now I am looking for a way to handle that click-event properly. See below the code I have so far:
cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
# now lets define a toast-message:
$toastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
$xmlString = #"
<toast launch = "Test1" scenario='alarm'>
<visual>
<binding template="ToastGeneric">
<text>Title</text>
<text>Message</text>
</binding>
</visual>
<audio src="ms-winsoundevent:Notification.Looping.Alarm" />
<actions>
<action content="yes" arguments="yes" />
<action content="no" arguments="no" />
</actions>
</toast>
"#
$toastXml.LoadXml($XmlString)
$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
$appId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
$notify = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId)
$notify.Show($toast)
Here I need a way to wait for the event, when the users clicks the "yes/no" buttons in the toast (or the "x" to close all). It should work without an external DLL, but using e.g. "add_Activated" and an eventHandler like in this c# code:
https://github.com/david-risney/PoshWinRT/blob/master/PoshWinRT/EventWrapper.cs
I thought it should be similar like for the other cs-Wrapper from that PoshWinRT project, which I could finally convert into this:
# replacement for PoshWinRT - AsyncOperationWrapper:
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$asTaskGeneric = foreach($method in [System.WindowsRuntimeSystemExtensions].GetMethods()) {
if ($method.name -ne 'AsTask') {continue}
if ($method.GetParameters().Count -ne 1) {continue}
if ($method.GetParameters().ParameterType.Name -ne 'IAsyncOperation`1') {continue}
$method
break
}
function Await($WinRtTask, $ResultType) {
$asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
$netTask = $asTask.Invoke($null, #($WinRtTask))
$null = $netTask.Wait(-1)
$netTask.Result
}
# sample for async operation:
$null = [Windows.Storage.StorageFile, Windows.Storage, ContentType = WindowsRuntime]
$file = 'c:\windows\notepad.exe'
$info = await ([Windows.Storage.StorageFile]::GetFileFromPathAsync($file)) ([Windows.Storage.StorageFile])
$info
Unfortunately, the coding for that eventWrapper seesm to be a bit more tricky. These are the code-snippets that I could not bring to life, but they may point into the right direction:
$method = [Windows.UI.Notifications.ToastNotification].GetMethod('add_Activated')
$handler = [Windows.Foundation.TypedEventHandler[Windows.UI.Notifications.ToastNotification,System.Object]]::new($toast, $intPtr1)
$handler = [System.EventHandler]::new($toast, $intPtr2)
Especially the second IntPtr-parameter required for creating an eventHandler confuses me totally.
Any input is more than welcome. Many thanks.

Powershell Code from Script Runs Within a PowerShell ISE Session - The Script myscript.ps1 does not run from PS>myscript.ps1 [duplicate]

This question already has an answer here:
Character-encoding problem with string literal in source code
(1 answer)
Closed last year.
When I launch a powershell session via powershell.exe and at the PS> prompt enter myscript.ps1 it errors with -
PS D:\TEST> D:\TEST\testrun.ps1
Missing ')' in method call.
At D:\TEST\testrun.ps1:1 char:65
$factory = [System.Data.Common.DbProviderFactories]::GetFactory( <<<< â?oIBM.
Data.DB2â??)
CategoryInfo : ParserError: (CloseParenToken:TokenId) [], Parse
Exception
FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
What is the reason for it working when running the lines of code individually via CutNPaste into ISE and launching? I receive the email with a nice table from the db extraction when I run it via ISE. This error is probably why it doesn't run in TaskScheduler as well.
$factory = [System.Data.Common.DbProviderFactories]::GetFactory(“IBM.Data.DB2”)
$cstrbld = $factory.CreateConnectionStringBuilder()
$cstrbld.Database = 'dbname'
$cstrbld.UserID = 'USER'
$cstrbld.Password = 'password'
$cstrbld.Server = 'server:50001'
$dbconn = $factory.CreateConnection()
$dbconn.ConnectionString = $cstrbld.ConnectionString
$dbconn.Open()
$dbcmd = $factory.CreateCommand()
$dbcmd.Connection = $dbconn
########################################################################################################################################
$dbcmd.CommandText = 'SELECT PFIWORKUNIT,ACTOR,FLOWDEFINITION,WORKTITLE,STATUS FROM APPLICATION.PFIWORKUNIT WHERE STATUS BETWEEN 0 AND 3'
########################################################################################################################################
$dbcmd.CommandType = [System.Data.CommandType]::Text
$da = $factory.CreateDataAdapter()
$da.SelectCommand = $dbcmd
$ds = New-Object System.Data.DataSet
$da.Fill($ds) | Out-Null
$dbconn.Close()
ForEach ($row in $ds.Tables[0].Rows) {
$ExciterObject = New-Object PSObject
$ExciterObject | Add-Member -MemberType NoteProperty -Name "PFIWORKUNIT" -Value $row.PFIWORKUNIT
$ExciterObject | Add-Member -MemberType NoteProperty -Name "ACTOR" -Value $row.ACTOR
$ExciterObject | Add-Member -MemberType NoteProperty -Name "FLOWDEFINITION" -Value $row.FLOWDEFINITION
$ExciterObject | Add-Member -MemberType NoteProperty -Name "WORKTITLE" -Value $row.WORKTITLE
$ExciterObject | Add-Member -MemberType NoteProperty -Name "STATUS" -Value $row.STATUS
$exportObject += $ExciterObject
}
function ConvertTo-HTMLTable ($obj) {
# Accepts a System.Data.DataTable object or an array of PSObjects and converts to styled HTML table
# add type needed to replace HTML special characters into entities
Add-Type -AssemblyName System.Web
$sb = New-Object -TypeName System.Text.StringBuilder
[void]$sb.AppendLine('<table>')
if ($null -ne $obj) {
if (([object]$obj).GetType().FullName -eq 'System.Data.DataTable'){
# it is a DataTable; convert to array of PSObjects
$obj = $obj | Select-Object * -ExcludeProperty ItemArray, Table, RowError, RowState, HasErrors
}
$headers = $obj[0].PSObject.Properties | Select -ExpandProperty Name
[void]$sb.AppendLine('<thead><tr>')
foreach ($column in $headers) {
[void]$sb.AppendLine(('<th>{0}</th>' -f [System.Web.HttpUtility]::HtmlEncode($column)))
}
[void]$sb.AppendLine('</tr></thead><tbody>')
$row = 0
$obj | ForEach-Object {
# add inline style for zebra color rows
if ($row++ -band 1) {
$tr = '<tr style="background-color: {0};">' -f $oddRowBackColor
}
else {
$tr = '<tr>'
}
[void]$sb.AppendLine($tr)
foreach ($column in $headers) {
[string]$val = $($_.$column)
#If($NameAd -ne "")
if ($val -notmatch "\S") {
$td = '<td> </td>'
}
else {
$td = '<td>{0}</td>' -f [System.Web.HttpUtility]::HtmlEncode($val)
}
[void]$sb.Append($td)
}
[void]$sb.AppendLine('</tr>')
}
[void]$sb.AppendLine('</tbody>')
}
[void]$sb.AppendLine('</table>')
return $sb.ToString()
}
$headerBackColor = '#4F81BD' # backgroundcolor for column headers
$oddRowBackColor = '#DCE6F1' # background color for odd rows
$style = #"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Report</title>
<meta name="generator" content="PowerShell" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
body {
font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
font-size: 12px;
color: black;
}
table, td, th {
border-color: black;
border-style: solid;
font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
font-size: 11px;
}
table {
border-width: 0 0 1px 1px;
border-spacing: 0;
border-collapse: collapse;
}
td, th {
margin: 0;
padding: 4px;
border-width: 1px 1px 0 0;
text-align: left;
}
th {
color: white;
background-color: $headerBackColor;
font-weight: bold;
}
</style>
<p><span style="color: #0000ff;"><strong>I'm only pulling only 1 thru 3 for a short email list</strong></span></p>
<p><span style="color: #0000ff;"><strong>WORK UNIT STATUS LEVELS BELOW:</strong></span></p>
<ol>
<li>01 = (<span style="color: #3366ff;"><strong>Ready for processing</strong></span>) using your SA account.</li>
<li>02 = (<span style="color: #3366ff;"><strong>Processing in progresst</strong></span>) using your SA account.</li>
<li>03 = (<span style="color: #3366ff;"><strong>Processing failed</strong></span>) using your SA account.</li>
<li>04 = (<span style="color: #3366ff;"><strong>Processing completed</strong></span>) using your SA account.</li>
<li>05 = (<span style="color: #3366ff;"><strong>Cancellation requested</strong></span>) using your SA account.</li>
<li>06 = (<span style="color: #3366ff;"><strong>Cancellation in progress</strong></span>) using your SA account.</li>
<li>07 = (<span style="color: #3366ff;"><strong>Cancellation failed</strong></span>) using your SA account.</li>
<li>08 = (<span style="color: #3366ff;"><strong>Cancellation completed</strong></span>) using your SA account.</li>
</ol>
"#
####SET EMAIL VALUES####
$bodyA = '{0}</head><body>{1}</body></html>' -f $style, (ConvertTo-HTMLTable $exportObject)
$EmailTo = "you#you.org"
$EmailFrom = "me#me.org"
$Subject = "Failed Work Unit Issue - High Priority"
$Body = $bodyA
$SMTPServer = "mail.server.org"
####EMAIL PROCESS ####
$anonUsername = "anonymous"
$anonPassword = ConvertTo-SecureString -String "anonymous" -AsPlainText -Force
$anonCredentials = New-Object System.Management.Automation.PSCredential($anonUsername,$anonPassword)
Send-MailMessage -smtpserver "$SMTPServer" -from "$EmailFrom" -to "$EmailTo" -subject "$Subject" -bodyAsHtml "$Body" -credential $anonCredentials
Exit
The quotes in the below section aren't standard, so the compiler is interpreting them as other characters.
$factory = [System.Data.Common.DbProviderFactories]::GetFactory(“IBM.Data.DB2”)
Note a regular ascii double quote is "034", but if you copy and paste one of the quote symbols from above into an ascii converter you'll get "226 128 156" as the ascii code instead.
TL;DR watch out for symbols that look a lot like the one you think you're using but aren't.

Access to REST Sharepoint data from another domain

Have this question: how I can do REST calls to Sharepoint 2013/2016 REST api, from another host, lets say, another server, but within the same domain.
By default, CORS policy will deny any request that does not come from the same host.
I am trying to retrieve some information doing an AJAX REST request from another host.
Thanks!!
Enable SharePoint configure to enable cross domain access.
Below script is shared by Ingo Karstein here
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0
$localFarm = Get-SPFarm
$webapp = Get-SPWebApplication "http://sp:12001"
# Remove old web.config modifications of MyAuthenticationProvider
$oldMods = #();
$webapp.WebConfigModifications | ? { $_.Owner -eq "CrossSiteScripting" } | % {
$oldMods = $oldMods + $_
}
$oldMods | % {
$webapp.WebConfigModifications.Remove($_)
}
# update the Web Application and apply all existing web.config modifications - this executes the "remove" actions from above
$webapp.Update()
[Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications()
#Wait until web.config modifications finished by timer job
while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) {
Write-Host "." -NoNewline
Start-Sleep 1
}
# New web.config modifications for MyAuthenticationProvider
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Allow-Origin'][#value='http://wfm:13002']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
#0 = for the enum value "SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Allow-Origin' value='http://wfm:13002' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Request-Method'][#value='GET,POST,HEAD,OPTIONS']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Request-Method' value='GET,POST,HEAD,OPTIONS' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Request-Headers'][#value='Content-Type,Authorization']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Request-Headers' value='Content-Type,Authorization' />"
$webapp.WebConfigModifications.Add($myModification1)
$myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification
$myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders"
$myModification1.Name = "add[#name='Access-Control-Allow-Credentials'][#value='true']"
$myModification1.Sequence = 0
$myModification1.Owner = "CrossSiteScripting"
$myModification1.Type = 0
$myModification1.Value = "<add name='Access-Control-Allow-Credentials' value='true' />"
$webapp.WebConfigModifications.Add($myModification1)
$webapp.Update()
[Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications()
#Wait until web.config modifications finished by timer job
while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) {
Write-Host "." -NoNewline
Start-Sleep 1
}
My test result:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<input id="Button1" type="button" onclick="getListItems()" value="button" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
function getListItems() {
var dataEndPoint = "http://sp:12001/_api/web/lists/getbytitle('Versions')/items";
$.ajax({
url: dataEndPoint,
type: "GET",
headers: {
"Accept": "application/json;odata=verbose"
},
crossDomain: true,
xhrFields: { withCredentials: true },
success: function (data) {
alert(data.d.results.length);
},
error: function (response) {
alert("Error");
}
})
}
</script>
</body>
</html>

Powershell - free disk space alert - add Test-connection

Ok, i try add Test-Connection and now the code look likes this:
$html=
#'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML TABLE</title>
<style type="text/css">
.alert {{
background-color: #FB1717 }}
.statusCom {{
background-color: #FB1717
}}
</style>
</head>
<body>
<table>
<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup>
<tr><th>SystemName</th><th>DeviceID</th><th>VolumeName</th><th>Size(GB)</th><th>FreeSpace(GB)</th><th>Status</th></tr>
{0}
</table>
</body></html>
'#
$entryTemplate = '<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>'
$alertEntryTemplate = '<tr class="alert"><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>'
$statusTemplate = '<tr class="statusCom"><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td><td>{7}</td></tr>'
Function Get-ComInfo {
param(
$computers
)
#Here LOW Space thresold is lessthan 10% of the total size of the Volume
$PercentFree = #{Name="FreeSpace(GB)";Expression={"{0:N1}" -f($_.freespace /1GB)}}
Get-WmiObject Win32_LogicalDisk -filter "DriveType=3" -computer $computers |
Select SystemName,DeviceID,VolumeName,$PercentFree,#{Name="Size(GB)";Expression={"{0:N1}" -f($_.size/1gb)}},#{name="PercentFree(%)";Expression={int}}
}
$servers = Get-Content U:\Users\xxx\Desktop\servers.txt
$client = $servers
if(Test-Connection -ComputerName (Get-Content U:\Users\xxx\Desktop\servers.txt ) -BufferSize 16 -Count 1 -Quiet) {
$entries = $servers | % { Get-ComInfo -computers $_ } | % {
if ([float]::Parse($_.'FreeSpace(GB)') -le 5) {
$alertEntryTemplate -f $_.SystemName, $_.DeviceID, $_.VolumeName, $_.'FreeSpace(GB)', $_.'Size(GB)', $_.'PercentFree(%)', $_.'LOW SPACE'
}
else {
$entryTemplate -f $_.SystemName, $_.DeviceID, $_.VolumeName, $_.'FreeSpace(GB)', $_.'Size(GB)', $_.'PercentFree(%)', $_.'LOW SPACE'
}
}
}
else{
$statusTemplate -f $_.SystemName, $_.DeviceID, $_.VolumeName, $_.'FreeSpace(GB)', $_.'Size(GB)', $_.'PercentFree(%)', $_.'LOW SPACE', $_.'Status'
}
$html -f ($entries -join ' ') | out-file U:\Users\xxx\Desktop\Drivess.html
$OutputFile = "U:\Users\xxx\Desktop\Drivess.html"
$SMTPServer = "smtp.xxx.com"
$EmailFrom = "xxxx#xxx.com"
$EmailTo = "xxxx#xxx.com"
$Subject = "$computers PROGRES ;))"
$body = (Get-Content $OutputFile)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
$SMTPClient.EnableSsl = $false
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxx", "xxx");
$MailTextT = Get-Content -Path U:\Users\xxx\Desktop\Drivess.html -Raw
$msg = New-object Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $body)
$msg.IsBodyHTML = $true
$SMTPClient.Send($msg)
In html i add this:
.statusCom {{
background-color: #FB1717
}}
And:
$statusTemplate = '<tr class="statusCom"><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td><td>{7}</td></tr>'
And i have more than one computer and one is offline in my servers.txt it i get this error:
Get-WmiObject : Serwer RPC it is offline. (Expectiob HRESULT: 0x800706BA)
At U:\Users\xxx\Desktop\test.ps1:36 char:1
+ Get-WmiObject Win32_LogicalDisk -filter "DriveType=3" -computer $comp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
If i have one computer and it is offline a get this:
<tr class="statusCom"><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
What i do wrong?
if (Test-Connection -ComputerName COMPUTERNAME_HERE -Count 1 -EA SilentlyContinue) { "online" } else { "offline" }
You Need to take this somewhere into your script, this should be easily done.
You can use the Systemname as Computername, provided by the Get-ComInfo function and you need to extent your two templates by a {7} for online/offline information.