Related
So I'm trying to pull the number of hours worked and the date worked from a table in my companies database to make a chart in Power BI through a streaming data set. I'm using powershell to parse a JSON file
Here's a JSON sample:
{"COUNT":"334","DISPLAY_LIST_START":"1","DISPLAY_LIST_STOP":"334","STOP":"334","RECORD":[{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/23/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/24/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/26/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/30/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/01/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["4",["05/02/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/03/2018"]]},{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/07/2018"]]},
I know it's not the best in terms of organization, but it's all I have to work with.
Here's the powershell code I have so far:
Invoke-WebRequest -Uri "http://wya.works/rta_develop/xmlServlet?&command=retrieve&sql=select%20%5B%24Hours%5D%2C%20%5B%24Date%20Worked%5D%20from%20%5B%21HOURS%5D%20&attributesOnly=Date%20Worked%2C%20Hours&contentType=JSON&referer=&time=1595443368507&key=696a6768"
$endpoint = "https://api.powerbi.com/beta/d6cdaa23-930e-49c1-9d2a-0fbe648551b2/datasets/91466553-d719-420c-9e3e-73e748379263/rows?noSignUpCheck=1&key=SU5GRBBWuuEIDSjqHW5hdgJzSMCQ3qUQ9mGrBDanjgpExv6woY1Sa1c3PC1Wk3WHHn1N%2FEpIuVgzHHcw0JXwYw%3D%3D"
$json.RECORD | Foreach-Object {
Write-Output "Checking Records"
$hours = 0
$date = ""
$json.FIELD | Foreach-Object{
Write-Output "Checking Field"
if ($_ -match '\d{1,2}/\d{1,2}\/d{4}'){
$date = $_
}
else {
$hours = $_
}
}
$payload = #{
"Hours" = $hours
"Date Worked" =$date
}
}
Invoke-RestMethod -Method Post -Uri "$endpoint" jlk-Body (ConvertTo-Json #($payload))
I need to parse through each record and pull the values of the hours (the numeric value in the JSON) and the Date (the date value).
When I run the code I don't get any errors, but it doesn't seem to be reaching the -match or the else statements. I tried logging the output on both and it returns nothing.
Is there something wrong with my loops?
I'm brand new to powershell and most of this code I got from help from other people, but I understand what its doing for the most part.
Also, anyone who knows about streaming datasets, will pulling this this way even give me what I want?
Store the Invoke-Webrequest values in your $json first. You missed that point; that's why you are getting Null.I don't know it is a typo or a miss.
Secondly, you $json.RECORD is wrong because it doesnt have any Record in the response. What you are looking for is basically the content. $json.content is going to give you the content of numbers.
$json=Invoke-WebRequest -Uri "http://wya.works/rta_develop/xmlServlet?&command=retrieve&sql=select%20%5B%24Hours%5D%2C%20%5B%24Date%20Worked%5D%20from%20%5B%21HOURS%5D%20&attributesOnly=Date%20Worked%2C%20Hours&contentType=JSON&referer=&time=1595443368507&key=696a6768"
Your endpoint and invoke-restmethod has nothing to do with your json parsing. First handle the response in the loop and see what is the outcome you are getting. I have structured it but I have not worked on the JSON sample data as if now:
$json=Invoke-WebRequest -Uri "http://wya.works/rta_develop/xmlServlet?&command=retrieve&sql=select%20%5B%24Hours%5D%2C%20%5B%24Date%20Worked%5D%20from%20%5B%21HOURS%5D%20&attributesOnly=Date%20Worked%2C%20Hours&contentType=JSON&referer=&time=1595443368507&key=696a6768"
$json.content | Foreach-Object {
Write-Output "Checking Records"
$hours = 0
$date = ""
$json.FIELD | Foreach-Object{
Write-Output "Checking Field"
if ($_ -match '\d{1,2}/\d{1,2}\/d{4}'){
$date = $_
}
else {
$hours = $_
}
}
$payload = #{
"Hours" = $hours
"Date Worked" =$date
}
}
$endpoint = "https://api.powerbi.com/beta/d6cdaa23-930e-49c1-9d2a-0fbe648551b2/datasets/91466553-d719-420c-9e3e-73e748379263/rows?noSignUpCheck=1&key=SU5GRBBWuuEIDSjqHW5hdgJzSMCQ3qUQ9mGrBDanjgpExv6woY1Sa1c3PC1Wk3WHHn1N%2FEpIuVgzHHcw0JXwYw%3D%3D"
Invoke-RestMethod -Method Post -Uri "$endpoint" jlk-Body (ConvertTo-Json #($payload))
The root of your problem is this:
$json.RECORD | Foreach-Object {
$json.FIELD | Foreach-Object{
...
}
}
Your outer foreach-object is looping over each item in the RECORD array, but the inner foreach-object is trying to loop over top-level FIELD properties that don't actually exist!
However, I think you'll hit more problems further along your code if you try to troubleshoot what you've already got, and there's an easier way to do what you're trying to do...
First, your sample json isn't quite valid - there's a trailing comma and some unclosed brackets so I'm going to reformat it with some line breaks so it's easier to read, and then fix it.
Note - you'll get the text from your call to Invoke-WebRequest, or as #Lee_Dailey suggested, Invoke-RestMethod.
# reformat the json, fix it, and assign it to a variable using a "Here-String"
# (see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7#here-strings)
$text = #"
{
"COUNT":"334",
"DISPLAY_LIST_START":"1",
"DISPLAY_LIST_STOP":"334",
"STOP":"334",
"RECORD":[
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/23/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/24/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/26/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["04/30/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/01/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["4",["05/02/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/03/2018"]]},
{"SESSION_ID":"c_a7FdTFicmxBJh9kln4V6gKxz_QErcufE7URF9m","FIELD":["6",["05/07/2018"]]}
]
}
"#
Then, we'll parse it - i.e. convert it from a string into an object model with well-defined properties:
# parse the json text
$json = $text | ConvertFrom-Json
And then process each record in turn:
$json.RECORD | ForEach-Object {
# get the number of hours worked. this is the first value in the FIELD array
# (note - the array starts at index 0 because it's zero-indexed)
$hours = $_.FIELD[0] # e.g. "6"
# get the "date worked". we need to get the second value (index 1) in
# the FIELD array, but this is a nested array, so once we've got the
# inner array we need to get the first value (index 0 again) from that
$date = $_.FIELD[1][0] # e.g. "04/23/2018"
# now we can build the payload...
$payload = #{
"Hours" = $hours
"Date Worked" = $date
}
# ...and invoke the api for this record
$endpoint = "https://api.powerbi.com/beta/d6cdaa23-930e-49c1-9d2a-0fbe648551b2/datasets/91466553-d719-420c-9e3e-73e748379263/rows?noSignUpCheck=1&key=SU5GRBBWuuEIDSjqHW5hdgJzSMCQ3qUQ9mGrBDanjgpExv6woY1Sa1c3PC1Wk3WHHn1N%2FEpIuVgzHHcw0JXwYw%3D%3D"
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json #($payload))
}
Note the api call is inside the foreach loop, otherwise you end up calculating the $payload for each RECORD but only ever actually calling the api for the last one.
(I've also removed a spurious "jlk" from your final line, which is probably a typo).
I have created a script to crawl the IMDB website. My script take a list of IMDB urls, run and extract the data like movie title, release year, plot summary and export it to a text file in CSV. I wrote the script as below.
$listToCrawl = "imdb_link_list.txt"
$pathOfFile = "K:\MY DOCUMENTS\POWERSHELL\IMDB FILE\"
$fileName = "plot_summary.txt"
New-Item ($pathOfFile + $fileName) -ItemType File
Set-Content ($pathOfFile + $fileName) '"Title","Year","URL","Plot Summary"'
Get-Content ($pathOfFile + $listToCrawl) | ForEach-Object {
$url = $_
$Result = Invoke-WebRequest -Uri $url
$movieTitleSelector = "#title-overview-widget > div.vital > div.title_block > div > div.titleBar > div.title_wrapper > h1"
$movieTitleNode = $Result.ParsedHtml.querySelector( $movieTitleSelector)
$movieTitle = $movieTitleNode.innerText
$movieYearSelector = "#titleYear"
$movieYearNode = $Result.ParsedHtml.querySelector($movieYearSelector)
$movieYear = $movieYearNode.innerText
$plotSummarySelector = "#titleStoryLine > div:nth-child(3) > p > span"
$plotSummaryNode = $Result.ParsedHtml.querySelector($plotSummarySelector)
$plotSummary = $plotSummary.innerText
$movieDataEntry = '"' + $movieTitle + '","' + $movieYear + '","' + $url + '","' + $plotSummary + '"'
Add-Content ($pathOfFile + $fileName) $movieDataEntry
}
The list of urls to extract from is saved in the "K:\MY DOCUMENTS\POWERSHELL\IMDB FILE\imdb_link_list.txt" file and the content is as below.
https://www.imdb.com/title/tt0472033/
https://www.imdb.com/title/tt0478087/
https://www.imdb.com/title/tt0285331/
https://www.imdb.com/title/tt0453562/
https://www.imdb.com/title/tt0120577/
https://www.imdb.com/title/tt0416449/
I just import and run the script. It does not run as expected. The error is threw.
Invalid argument.
At K:\MY DOCUMENTS\POWERSHELL\IMDB_Plot_Summar_ Extract.ps1:20 char:1
+ $plotSummaryNode = $Result.ParsedHtml.querySelector($plotSummarySelec ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
I think the problem is due to the CSS selector I use to select the data but I don't know what's wrong. I think I have followed the CSS selector rule.
$plotSummarySelector = "#titleStoryLine > div:nth-child(3) > p > span"
Does anyone know what's wrong with the thing.
The ParsedHtml property is specific to PowerShell for Windows and doesn't exist in PowerShell Core, so if you want to future-proof your code you're better off using something like the HTML Agility Pack.
# install the HTML Agility Pack nuget package
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile ".\nuget.exe";
.\nuget.exe install "HtmlAgilityPack" -Version "1.11.21";
# import the HTML Agility Pack
Add-Type -Path ".\HtmlAgilityPack.1.11.21\lib\Net40\HtmlAgilityPack.dll";
# get the web page content and load it into a HtmlDocument
$response = Invoke-WebRequest -Uri "https://www.imdb.com/title/tt0472033/" -UseBasicParsing;
$html = $response.Content;
$doc = new-object HtmlAgilityPack.HtmlDocument;
$doc.LoadHtml($html);
then you can extract nodes using XPath syntax - e.g. for the title:
# extract the title
$titleHtml = $doc.DocumentNode.SelectSingleNode("//div[#class='title_wrapper']/h1/text()[1]").InnerText;
$titleText = [System.Net.WebUtility]::HtmlDecode($titleHtml).Trim();
write-host "'$titleText'"; # '9'
I'll leave the rest of the document elements as an exercise for the reader :-).
When making a POST call with curl I'm having trouble getting the JSON data to be passed correctly. The string is cut off at the first whitespace/blank space.
My call looks like this, I'm executing through a powershell script that has two parameters. Using these parameters I concatenate the JSON that is used for the call.
I input for instance 854e-ae7686fbc75a 365 as parameters
# usage: powershell -file send.ps1 [apitoken] [interval]
param (
[string]$apitoken = "",
[int]$startInterval = "365"
)
$AUTHORIZATION = $apitoken
$STARTDATE = (Get-Date).AddDays(-$startInterval)
$ENDDATE = (Get-Date)
$JSON = '{\"ApiToken\":\"' + $AUTHORIZATION + '\",' +
'\"StartDate\":\"' + $STARTDATE + '\",' +
'\"EndDate\":\"' + $ENDDATE + '\",' +
'\"Type\":\"SalesExport\"' +
'}'
$CURLEXE = '..\bin\curl.exe'
$CurlArgument = '-X', 'POST',
'-m', 7200,
'-H', '"Content-Type:application/json"',
'-d', $JSON,
'https://my.server/export/sales'
& $CURLEXE #CurlArgument
The STARTDATE would then be the current date minus 365 days. ENDDATE would be the current date.
The problem is as soon as there is a blank space (or possibly any whitespace) in the JSON variable curl thinks that the JSON has ended and says that the JSON is unterminated. There is no difference if I surround the variable with single or double quotes.
Even if the whitespace is inside one of the two DateTime variables the problem occurs!
How can I format the JSON properly so that it can include whitespace?
Not a direct answer to your question, but since you're using PowerShell anyway: why not use the native Invoke-WebRequest instead of an external command?
$today = (Get-Date).Date
$uri = 'https://example.org/export/sales'
$headers = #{
'Content-Type' = 'application/json'
}
$data = #{
'ApiToken' = $apitoken
'StartDate' = $today.AddDays(-$startInterval).ToString('d')
'EndDate' = $today.ToString('d')
'Type' = 'SalesExport'
} | ConvertTo-Json
Invoke-WebRequest -Method Post -Headers $headers -Body $data -Uri $uri
Alternatively you can define the JSON data as a multiline string:
$startDate = $today.AddDays(-$startInterval).ToString('d')
$endDate = $today.ToString('d')
$data = #"
{
"ApiToken": "$apitoken",
"StartDate": "$startDate",
"EndDate": "$endDate",
"Type": "SalesExport"
}
"#
First of all thank you in advance. I am trying to retrieve the following values from the JSON string below using PowerShell but am having issues.
ScheduleTitle,
Title,
Environment and Title
Resolution,
Width,
Height
JSON:
{"Id":"d52fb00e-8736-448c-a496-96db6bc2eb43","ScheduleId":"275726dc-09f2-4869-b1a0-54c71ef6a093","ScheduleTitle":"Resolution Testing","RunType":"RunNow","Timestamp":"2017-08-01T04:52:19.2039685","AutomationRunItems":[{"Id":"f7b731fb-cd96-4003-b95c-ef1594f1c86e","AutomationRunId":"d52fb00e-8736-448c-a496-96db6bc2eb43","Status":"Done","Case":{"Id":"c8a0b939-54ba-4b98-8ca9-101093aec26f","Title":"Resolution Test"},"Environment":{"Id":"e1783fb5-4001-45d0-9971-b49c31b374ab","Title":"Se Chrome"},"Keyframes":[{"Timestamp":"2017-08-01T04:52:03.0685609","Elapsed":"00:00:00","Level":"Info","Status":"Connecting","BlockId":"78c198ac-b61f-40eb-b1d9-e706546f2be3","LogMessage":"Connecting to Se Chrome: Selenium Grid (localhost:5559) on Chrome with size 1280x1024"},{"Timestamp":"2017-08-01T04:52:03.0685609","Elapsed":"00:00:00.0000003","Level":"Info","Status":"Connected","BlockId":"78c198ac-b61f-40eb-b1d9-e706546f2be3","LogMessage":"Connected"},{"Timestamp":"2017-08-01T04:52:03.0685609","Elapsed":"00:00:00.0000015","Level":"Info","Status":"Running","BlockId":"78c198ac-b61f-40eb-b1d9-e706546f2be3","LogMessage":"Running"},{"Timestamp":"2017-08-01T04:52:03.0695642","Elapsed":"00:00:00.0003729","Level":"Trace","Status":"Running","BlockId":"78c198ac-b61f-40eb-b1d9-e706546f2be3","LogMessage":"Block is executing."},{"Timestamp":"2017-08-01T04:52:03.5713896","Elapsed":"00:00:00.5020154","Level":"Trace","Status":"Running","BlockId":"78c198ac-b61f-40eb-b1d9-e706546f2be3","LogMessage":"Block is executed."},{"Timestamp":"2017-08-01T04:52:03.5713896","Elapsed":"00:00:00.5021370","Level":"Trace","Status":"Running","BlockId":"302f21b8-a279-48ce-9338-580a97c930fd","LogMessage":"Block is executing."},{"Timestamp":"2017-08-01T04:52:06.9793063","Elapsed":"00:00:03.9107459","Level":"Info","Status":"Running","BlockId":"302f21b8-a279-48ce-9338-580a97c930fd","LogMessage":"Chrome was successfully started"},{"Timestamp":"2017-08-01T04:52:09.4641639","Elapsed":"00:00:06.3955903","Level":"Info","Status":"Running","BlockId":"302f21b8-a279-48ce-9338-580a97c930fd","LogMessage":"Chrome loaded url https://dev.bamapplication.com/app/starke/npr/3BF6DA09C1/wizard"},{"Timestamp":"2017-08-01T04:52:09.7604882","Elapsed":"00:00:06.6925088","Level":"Trace","Status":"Running","BlockId":"302f21b8-a279-48ce-9338-580a97c930fd","LogMessage":"Block is executed."},{"Timestamp":"2017-08-01T04:52:09.7604882","Elapsed":"00:00:06.6926471","Level":"Trace","Status":"Running","BlockId":"26382d5d-60a6-4343-b934-265c4e97186d","LogMessage":"Block is executing."},{"Timestamp":"2017-08-01T04:52:10.4639126","Elapsed":"00:00:07.3954580","Level":"Warning","Status":"Running","BlockId":"26382d5d-60a6-4343-b934-265c4e97186d","LogMessage":"Web screenshot is saved"},{"Timestamp":"2017-08-01T04:52:10.7666916","Elapsed":"00:00:07.6982198","Level":"Trace","Status":"Running","BlockId":"26382d5d-60a6-4343-b934-265c4e97186d","LogMessage":"Block is executed."},{"Timestamp":"2017-08-01T04:52:10.7666916","Elapsed":"00:00:07.6983727","Level":"Trace","Status":"Running","BlockId":"161e621f-bb7a-4f42-a5f1-67e07d1432f4","LogMessage":"Block is executing."},{"Timestamp":"2017-08-01T04:52:11.7677637","Elapsed":"00:00:08.6992111","Level":"Info","Status":"Done","BlockId":"161e621f-bb7a-4f42-a5f1-67e07d1432f4","LogMessage":"Case is stopped."}],"Resolution":{"Width":1280,"Height":1024},"Elapsed":"00:00:08.6992111","CreatedAt":"2017-08-01T04:52:19.2039685","ModifiedAt":"2017-08-01T04:52:19.2039685"}],"ProjectId":"275726dc-09f2-4869-b1a0-54c71ef6a093","ExecutionTotalTime":"00:00:08.6992111","FailedCount":0,"PassedCount":0,"DoneCount":1,"CreatedAt":"2017-08-01T04:52:03.0685609"}
Code:
Param( [string]$result, [string]$rootPath )
try{
$json = $result
$parsed = $json | ConvertFrom-Json
$output= ''
foreach ($line in $parsed | Get-Member) {
Write-Output $parsed.$($line.Resolution).property1
Write-Output $parsed.$($line.Resolution).property2
$output += $parsed.$($line.Resolution).property1 + " " + $parsed.$($line.Resolution).property1
}
}
With your $parsed data you can extract all the information you need.
For example to extract the width:
echo $parsed.AutomationRunItems.Resolution.Width
should print: 1280
I think these are all the fields you need extracted. Note, since you did not specify the output precisely I have simply used comma-delimited strings:
$output= ''
$output = $output + $parsed.ScheduleTitle + ','
$output = $output + $parsed.AutomationRunItems.Case.Title + ','
$output = $output + $parsed.AutomationRunItems.Environment.Title + ','
$output = $output + $parsed.AutomationRunItems.Resolution.Width + ','
$output = $output + $parsed.AutomationRunItems.Resolution.Height
Should Print: Resolution Testing,Resolution Test,Se Chrome,1280,1024
I was almost done with my script and did some late night editing and written over my old version so I cannot go back.
The script was running fine, still needed some tweaks but now it ha come to a complete halt.
The idea is to GC a list of IP's. Resolve the IP's and place them in an excel sheet. Then save the sheet to htm and xlsx. And finally mailing those to me.
Now it gets stuck on sorting the sheet, saving AND mailing...
Can someone give me some insight on what I did wrong here?
it gets stuck on sorting the sheet, saving AND mailing.
It no longer sorts B3:B$Count:
Exception calling "Sort" with "1" argument(s): "The sort reference is not valid. Make sure that it's within the data you want to sort, and the first Sort By box isn't the same or blank."
At C:\Folder\Scripts\Get-IP.ps1:137 char:5
+ [void] $objRange.Sort($objRange2)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
It no longer saves the xlsx file, but does save the HTM file. It is clearly not overwriting something. I even restarted to make sure.
Exception calling "SaveAs" with "1" argument(s): "Microsoft Excel cannot access the file 'C://Folder/BlockedIP/HTML/2014-07-08/0BCEF810'. workbook."
At C:\Folder\Scripts\Get-IP.ps1:160 char:5
+ $b.SaveAs("$FileXML")
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
And finally, it will no longer send me e-mails:
New-Object : Exception calling ".ctor" with "2" argument(s): "The specified string is not in the form required for an e-mail address."
At C:\Folder\Scripts\Get-IP.ps1:217 char:13
+ $SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
The script:
#Get current date
$Date = get-date -format yyyy-MM-dd
#Define all files/Paths.
$Path = "C:/Folder/BlockedIP"
md "$Path/HTML/$Date" -Force
$path2 = "$Path/HTML/$Date"
$PathWeb = "/HTML/$Date"
#Define File's used or created in this script.
$File = "$Path/IP-$Date.txt"
$FileHtml = "$Path2/IP-$Date.htm"
$FileXML = "$Path2/IP-$Date.xlsx"
$FileHTMLWeb = "$PathWeb/IP-$date.htm"
#Get content from given IP list.
$colComputers = #(get-content $File | Sort -unique)
$count = $colComputers.Count
write-output "$Count IP's detected."
#Define error actions.
#$erroractionpreference = "SilentlyContinue"
#Open Excel.
$a = New-Object -comobject Excel.Application
#Since we want this script to look like it's being used without excel I set it's visibility to false.
$a.visible = $True
#Disable excel confirmations.
$a.DisplayAlerts = $False
#Create sheets in Excel.
$b = $a.Workbooks.Add()
$c = $b.Worksheets.Item(1)
#Create a Title for the first worksheet and adjust the font
$row = 1
$Column = 1
target="_parent">Creator'
$c.Cells.Item($row,$column)= "Blocked IP's $Date"
$c.Cells.Item($row,$column).Font.Size = 18
$c.Cells.Item($row,$column).Font.Bold=$True
$c.Cells.Item($row,$column).Font.Name = "Cambria"
$c.Cells.Item($row,$column).Font.ThemeFont = 1
$c.Cells.Item($row,$column).Font.ThemeColor = 4
$c.Cells.Item($row,$column).Font.ColorIndex = 55
$c.Cells.Item($row,$column).Font.Color = 8210719
$range = $c.Range("a1","e1")
$range.Merge() | Out-Null
$range.VerticalAlignment = -4160
#Define subjects.
$c.Name = "Blocked IP's ($Date)"
$c.Cells.Item(2,1) = "Given IP"
$c.Cells.Item(2,2) = "Resolved DNS"
$c.Cells.Item(2,3) = "Returned IP"
$c.Cells.Item(2,5) = "Company name"
#Define cell formatting from subjects.
$c.Range("A2:E2").Interior.ColorIndex = 6
$c.Range("A2:E2").font.size = 13
$c.Range("A2:E2").Font.ColorIndex = 1
$c.Range("A2:E2").Font.Bold = $True
#Define the usedrange for autofitting.
$d = $c.UsedRange
#Make everything fit in it's cell
$D.EntireColumn.AutoFit() | Out-Null
#Define html code for Excel save to .htm.
$xlExcelHTML = 44
#Define rows to alter in excel.
$iRow = 3
$intRow = 3
#Time to run the script.
foreach ($strComputer in $colComputers)
{
#Place IP's from text in the excel sheet
$c.Cells.Item($intRow, 1) = $strComputer.ToUpper()
$d.EntireColumn.AutoFit() | Out-Null
#Create a status bar for the script
$i = 1
Write-Progress -Activity `
"Creating a usable 'Blocked IP' list ($i/$count)" `
-PercentComplete ($i/$colComputers.Count*100) `
-Status "Please stand by"
try {
$dnsresult = [System.Net.DNS]::GetHostEntry($strComputer)
}
catch {
$dnsresult = "$null"
}
#Clear screen on every checked IP to remove the 'True' statement.
#cls
#Do something with $dnsresults.
#Display information about host
#Give hostname Entry in Cell2
$c.Cells.Item($intRow,2) = $dnsresult.HostName
#IP listed in Cell 3
$c.Cells.Item($intRow,3) = $dnsresult.AddressList[0].IpAddressToString
#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null
#Define row for the IP list.
$intRow = $intRow + 1
#Set background color for the IP list.
$d.Range("A$($iRow):E$($intRow)").interior.colorindex = 15
#Sort all IP's on resolved name.
$objWorksheet = $b.Worksheets.Item(1)
$objRange = $objWorksheet.UsedRange
$objRange2 = $objworksheet.Range("B3:B($Count)")
[void] $objRange.Sort($objRange2)
#Define borders here.
<# Insert script :D #>
#Define Filters here. (Picking out blank DNS and giving those a name)
<# Insert script :D #>
#Define Filters here. (Picking out specific DNS name and give them color code)
<# Insert script :D #>
#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null
#Clear screen on every checked IP to remove the 'True' statement.
#cls
}
#Save the file as .xlsx on every placed IP to ensure the file is not lost due to any reason.
$b.SaveAs("$FileXML")
#Save final result as a .htm file
$b.SaveAs("$FileHTML",$xlExcelHTML)
#Close and quit Excel.
$b.Close()
get-process *Excel* | Stop-Process -force
#Move .txt file to the correct HTML folder.
move-item $file $path2 -Force
#Clear screen, again. (Let's keep things tidy.)
#cls
#Variables for public IP
# I am defining website url in a variable
$url = "http://checkip.dyndns.com"
# Creating a new .Net Object names a System.Net.Webclient
$webclient = New-Object System.Net.WebClient
# In this new webdownlader object we are telling $webclient to download the
# url $url
$IpPublic = $webclient.DownloadString($url)
# Just a simple text manuplation to get the ipadress form downloaded URL
# If you want to know what it contain try to see the variable $IpPublic
$IpPublic2 = $IpPublic.ToString()
$ipPublic3 = $IpPublic2.Split(" ")
$ipPublic4 = $ipPublic3[5]
$ipPublic5 = $ipPublic4.replace("</body>","")
$FinalIPAddress = $ipPublic5.replace("</html>","")
#Variables e-mail.
$From = "Blocked IP <###g##.com>"
$To = "IT Dept <#####.nl>"
$CC = "Someone <##r###.nl"
$SMTP = "smtp.gmail.com"
$Subject = "Blocked IPs for $date ($Count Total)"
#The href should point to the htm file in your iis/apache folder.
$WebLink = $FinalIPAddress+$FileHtmlWeb
$here = "<a href='http://$Weblink'><b>Here</b></a>"
#Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
#A link to the .htm file, how many IP's were blocked and the date of the message.
$Body = "This is an automated message generated by server: $env:COMPUTERNAME, $IP</br></br>
Please see the attachment or click $here to get the $Count blocked IP's of $date. </br> </br></br>"
#Variables e-mail user.
$username = "#####.com"
$password = "##"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$ip = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0]
#Clear screen, again. (Let's keep things tidy.)
#cls
#Send output as e-mail.
$SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
$SMTP.EnableSsl = $true
$SMTP.Credentials = New-Object System.Net.NetworkCredential("$username", "$password");
$SMTP.isbodyhtml= $true
$SMTP.Send($From, $To, $Subject, $FileXML, $Body)
send-mailmessage -BodyAsHtml -from $From -to $To -cc $CC -subject $Subject -Attachments $FileXML -body $Body -priority High -smtpServer $SMTP -credential ($cred) -usessl
#Create a function to relase Com object at end of script.
function Release-Ref ($ref) {
([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
[System.__ComObject]$ref) -gt 0)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
#Release COM Object
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$a) | Out-Null
#Clear screen for the final time. (Let's keep things tidy.)
#cls
#Exit powershell
exit
Any help will be greatly appreciated!
Exception calling "Sort" with "1" argument(s): "The sort reference is not valid. Make sure that it's within the data you want to sort, and the first Sort By box isn't the same or blank."
Double-check that $objRange and $objRange2 reference the correct ranges:
$objRange.Address()
$objRange2.Address()
Not much else I can tell you here without seeing your actual data.
Exception calling "SaveAs" with "1" argument(s): "Microsoft Excel cannot access the file 'C://Folder/BlockedIP/HTML/2014-07-08/0BCEF810'. workbook."
If the path really were C://Folder/... you'd be getting a different exception. Please do not fabricate error messages.
New-Object : Exception calling ".ctor" with "2" argument(s): "The specified string is not in the form required for an e-mail address."
You're confusing MailMessage and SmtpClient class. Not to mention that you don't even need either of them, since you're using Send-MailMessage anyway. Just remove the following 5 lines:
$SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
$SMTP.EnableSsl = $true
$SMTP.Credentials = New-Object System.Net.NetworkCredential("$username", "$password");
$SMTP.isbodyhtml= $true
$SMTP.Send($From, $To, $Subject, $FileXML, $Body)
Solved the sorting problem by altering the code to:
$objRange = $c.Range("A$($iRow):E$($intRow)")
$objRange2 = $c.Range("B$($iRow):B$($intRow)")
[void] $objRange.Sort($objRange2)
Turns out it got stuck on the header in the xml file
Replaced mailing with:
$From = "Blocked IP <#####.##>"
$To = "IT Dept <#####.##>"
$CC = "Someone <#####.##"
$Subject = "Blocked IPs for $date ($Count Total)"
#The href should point to the htm file in your iis/apache folder.
$WebLink = $FinalIPAddress+$FileHtmlWeb
$here = "<a href='http://$Weblink'><b>Here</b></a>"
#Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
#A link to the .htm file, how many IP's were blocked and the date of the message.
$body = "Dear <font color=black>$to</font>,<br><br>"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "###gmail.com"
$Password = "##"
$message = New-Object System.Net.Mail.MailMessage
$message.IsBodyHTML = $true
$message.ReplyTo = $From
$message.Sender = $From
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.from = $username
$message.attachments.add($MailXML)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
The saving of the file turned out to be a misguided path.
Since the excel sheet was created from folder1 it wouldnt save instandly to folder 2 since its temp save file would remain in folder1.