How do I error handling in Invoke-WebRequest? - powershell

2022-12-01: проблема ЧАСТИЧНО решена к версии 7.3.
The documentation recommends «Try-Catch». The problems are as follows.
0. Update: https://github.com/PowerShell/PowerShell/issues/16145
The «Catch [System.Net.WebException]» option has never worked for me, «Catch [System.Management.Automation.RuntimeException]» has always been activated. It is activated when divided by zero, for example. Can they be separated into different groups?
For different errors, the method and property sets of the automatic variable «$_ » in the «Catch»-block are different. Accessing the method BEFORE ERROR UNDERSTANDING may cause a new error. So far, I see ONLY ONE constant parameter: «$_.Exception.HResult». Is it really the ONLY one? There is not a word in the documentation about this.
At the break of the connection during the downloading process (for example, the router rebooted) no error occurs at all, the next statement in the «Try»-block is executed and «$Error.Count» is not increased, and the file on the disk remains PARTIALLY downloaded (although with some types of content it may be absent, it seems). Is it normal?
The third-party utility «cURL» at break of connection return errors with NON-ZERO codes 18 and 28 (perhaps, and others, I don't remember for sure). In PowerShell is this possible?
Notabene: to reboot the router or disconnect the cable you must to use your hands, not sample of my code.
Removed.
The part of my program written in the language that I know (not English).
$Error.Count
Try {
    # Для самых НЕвнимательных ПОВТОРЯЮ И ПОДЧЁРКИВАЮ, что
    # меня интересуют ошибки «Invoke-WebRequest»,
    # а НЕ ДЕЛЕНИЯ. Как их отделить друг от друга?
    # Именно об этом я написал в исходном вопросе!
    <# 1/0 # Для проверки этого случая раскомментируйте вручную. #>
    Invoke-WebRequest -URI СсылкаНаБольшойФайл -ErrorAction Stop
    $Error.Count
} Catch [System.Net.WebException] { # In THIS order!
    "Эта секция не выполняется НИКОГДА."
} Catch [System.Management.Automation.RuntimeException] {
    "Эта секция выполняется ВСЕГДА при ошибках 1/0 and «IWR»."
    "Управление попадает сюда при ЛЮБЫХ ошибках из моего примера,"
    " КАК арифметических, ТАК и сетевых. Всё в одну кучу."
    # Для самых НЕвнимательных ПОВТОРЯЮ И ПОДЧЁРКИВАЮ, что
    # меня интересуют ошибки «Invoke-WebRequest»,
    # а НЕ ДЕЛЕНИЯ. Как их отделить друг от друга?
    # Именно об этом я написал в исходном вопросе!
    # Следующая строка может вызвать ошибку,
    # потому что такого метода/свойства просто нет.
    # А может выполниться БЕЗ прерывания. Как повезёт.
    $_.Exception.InnerException.ErrorCode
    "В документации НИ слова о том,"
    " какие элементы (методы/свойства) присутствуют ВСЕГДА."
} Catch [System.SystemException] { # In THIS order!
    "Эта секция не выполняется НИКОГДА."
} Catch { # In THIS order!
    "Эта секция не выполняется НИКОГДА."
}

So I've run your code and have observed the following:
PowerShell 5.1 emits a WebException on failure.
PowerShell 7 emits a System.Net.Http.HttpRequestException, if you catch that it would separate the web exceptions from your hypothetical divide by zero.
If the inner exceptions of your HttpRequestException is a SocketException then you can use the ErrorCode field to get the underlying Windows Sockets error:
try{
$res = Invoke-WebRequest -URI 'https://notexist.example.com/' -ErrorAction Stop
}catch[System.Net.Http.HttpRequestException]{
$_.exception.innerexception.errorcode
}
11001
A list of the possible codes is here: https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
However at this point you've got to ask yourself are you really going to take a different action in your code for a DNS failure, a connection failure, connection refused, and every other possible option on that list?
As for your final point, when I unplug the network cable PowerShell 7 just hangs indefinitely, that could be this open bug: https://github.com/PowerShell/PowerShell/issues/12249

Related

How to check if custom culture exists

I have created one custom culture as 'gh-es'. I am trying to check if its already registered.its working fine if culture is registered but if not it throw an error in start only.
I am unable to find how to check if a culture is present or to check if its exists
$CustomCulture= [cultureinfo]::GetCultureInfo('gh-es')
If($CustomCulture -ne null)
{
Write-output "culture already registered"
}
Else
{
$CultureName = 'gh-es'
$BaseCulture=[cultureinfo]::GetCultureInfo('es-US')
$BaseRegion = New-Object System.Globalization.RegionInfo 'es-US'
try {
# Set up CultureAndRegionInfoBuilder
Add-Type -AssemblyName sysglobl
$CultureBuilder = New-Object System.Globalization.CultureAndRegionInfoBuilder
#($CultureName,[System.Globalization.CultureAndRegionModifiers]::None) $CultureBuilder.LoadDataFromCultureInfo($BaseCulture)
$CultureBuilder.LoadDataFromRegionInfo($BaseRegion)
$CultureBuilder.Register()
}
catch
{
throw
}
}
this is what i mean by using try/catch to handle an error when checking for a culture ...
try {
[cultureinfo]::GetCultureInfo('666-santa')
}
catch
{
'something glitched'
}
the output = something glitched
without the try/catch, the output is an error msg ...
Exception calling "GetCultureInfo" with "1" argument(s): "Culture is not supported.
Parameter name: name
666-santa is an invalid culture identifier."
At line:1 char:1
+ [cultureinfo]::GetCultureInfo('666-santa')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CultureNotFoundException

Gammu on raspberry Zero

I am trying to setup a raspberry zero to collect the temperature from a DS18B20 probe connected to a -20°C fridge of my lab. If a temperature above a certain value is detected, the raspberry should send an email to alert for a a problem. I use a chinese (IEASUN Technology) HSUPA modem with a Qualcom chip. Gammu is used to communicate with the modem. After installing gammu and my script, everything worked as expected. Then, I decided to add a function: upon sending a sms to the raspberry, I wanted that it sent back the temperatures of the connected probes (and I had to install gammu-smsd). This new function is working but my original alert script does not work anymore.
I must emphasise that this is done as an autodidact with minimal knowledge in coding (this will be obvious in the code).
Here are several key information.
When I run my 'Alert' script, now, I have this message:
Traceback (most recent call last):
File "sendsmstemp.py", line 11, in <module>
sm.Init()
gammu.ERR_DEVICEOPENERROR: {'Text': u'Error opening device. Unknown, busy or no permissions.', 'Code': 2, 'Where': 'Init'}
The code of my 'Alert' script is:
import gammu
import sys
# Create state machine object
sm = gammu.StateMachine()
# Read ~/.gammurc
sm.ReadConfig()
# Connect to phone
sm.Init()
import time
while 1:
        tempfile1 = open("/sys/bus/w1/devices/28-031689cf76ff/w1_slave")
        thetext1 = tempfile1.read()
        tempfile1.close()
        tempdata1 = thetext1.split("\n")[1].split(" ")[9]
        temperature1 = float(tempdata1[2:])
        temperature1 = temperature1 / 1000
if temperature1>-10:
     
message1 = {
'Text': 'Time is:' + time.strftime('%H:%M:%S')+'| Temperature Fridge 1 above -10°C!! . If still above the limit, another sms will be sent in 30min',
'SMSC': {'Location': 1},
'Number': '+Myphonenumber',
'Validity': 'Max',
}
sm.SendSMS(message)
#It waits 30min before sending another sms
time.sleep(1800)
Else:
#test the probe every min
time.sleep(60)
This code is launched at startup with this sh script:
#!/bin/sh
sleep 10
sudo python /home/pi/smstemp/sendsmstemp.py
The last script that I have added to this raspberry — which required the installation of gammu-smsd package — that has apparently broken the first one is:
#!/bin/sh
from=$SMS_1_NUMBER
message=$SMS_1_TEXT
#ThisHost=$(hostname)
# local file to write into
#FILE=$ThisHost"-status.txt"
# local directory to write to file and pick it for upload
#REPERTOIRE="/home/pi/sendsmstemp/"
#echo $REPERTOIRE$FILE
#Read last temperature 
temperature1=$(find /sys/bus/w1/devices/ -name "28-*6ff" -exec cat {}/w1_slave \; | grep "t=" | awk -F "t=" '{print $2/1000}')
#Send message
reply=""
echo "Temp Fridge 1: $temperature1" | sudo gammu sendsms TEXT "$from"
Now, my /etc/gammu-smsdrc config file looks like that:
[gammu]
device = /dev/ttyUSB0
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
gammucoding = utf8
[gammu1]
device = /dev/ttyUSB1
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
gammucoding = utf8
[gammu2]
device = /dev/ttyUSB2
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
gammucoding = utf8
[gammu3]
device = /dev/ttyUSB3
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
gammucoding = utf8
[smsd]
service = files
#logfile = syslog
logfile = /var/spool/gammu/log/gammu-smsdrc.log
# Change PIN code
pin = 1234
RunOnReceive = /home/pi/sendsmstemp/sendinfo.sh
My /etc/gammurc config file is the same (except that the last line is not included).
The gamma-detect command returns that:
[gammu]
device = /dev/ttyUSB0
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
[gammu1]
device = /dev/ttyUSB1
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
[gammu2]
device = /dev/ttyUSB2
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
[gammu3]
device = /dev/ttyUSB3
name = Phone on USB serial port Qualcomm__Incorporated Qualcomm_CDMA_Technologies_MSM
connection = at
The gammu --identify returns that:
Device : /dev/ttyUSB1
Manufacturer : Qualcomm
Model : unknown (+CGMM:HSPA MODEM)
Firmware : +CGMR:V1.1
IMEI : 356793034431627
SIM IMSI : +CIMI:208150010138412
The gammu getsecuritystatus returns that:
Nothing to enter.
And using this command works as expected (it send a sms):
gammu sendsms TEXT 06xxxxxxxx -text "Test"
Why my 'Alert' script is not running??? I am lost.
Many many thanks for your help!!
As explained in my comment to my question, I gave up. I have amended and debugged the alert script, for those that might be interested (it works with 2 probes and it is easy to add other probes):
#!/usr/bin/env python
# encoding: utf-8
import gammu
import sys
# Create state machine object
sm = gammu.StateMachine()
# Read ~/.gammurc
sm.ReadConfig()
# Connect to phone
sm.Init()
import time
while 1:
    tempfile1 = open('/sys/bus/w1/devices/28-031689cf76ff/w1_slave')
    tempfile2 = open('/sys/bus/w1/devices/28-051691e603ff/w1_slave')
    thetext1 = tempfile1.read()
    thetext2 = tempfile2.read()
    tempfile1.close()
    tempfile2.close()
    tempdata1 = thetext1.split("\n")[1].split(" ")[9]
    tempdata2 = thetext2.split("\n")[1].split(" ")[9]
    temperature1 = float(tempdata1[2:])
    temperature2 = float(tempdata2[2:])
    temperature1 = temperature1 / 1000
    temperature2 = temperature2 / 1000
    if int(temperature1) > -10 or int(temperature2) > -10:
        #Tony
        message = {
        'Text': time.strftime('%H:%M') + '\r\nTemperature of a Team 1 Fridge above -10deg' + '\r\nFridge 1=' + str(temperature1) + 'deg\r\nFridge 2=' + str(temperature2) + 'deg\r\nIf still above the limit, another SMS will be sent in 30 min',
        'SMSC': {'Location': 1},
        'Number': '+336XXXXXXXXX',
        'Validity': 'Max',
        }
        sm.SendSMS(message)
        time.sleep(1800)
        #Check every min
        time.sleep(60)

The term 'Import-AzurePublishSettingsFile' is not recognized as the name of a cmdlet, function, script file, or operable program

The term 'Import-AzurePublishSettingsFile' is not recognized as the
name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the
path is correct and try again.
In visual studio its working fine but when I host the code on window server 2012 IIS then it giving above error.
c# code is
using (PowerShell PowerShellInstance = PowerShell.Create())
{
String SubscriptionFilePath = UtlityHelper.GetFilePath(Settings.Default.SubscriptionFile);
PowerShellInstance.AddScript("Import-AzurePublishSettingsFile -PublishSettingsFile " + "" + SubscriptionFilePath + "");
// PowerShellInstance.AddScript("Get-AzureSubscription | Out-String");
var result = PowerShellInstance.Invoke();
if (PowerShellInstance.Streams.Error.Count > 0)
{
foreach (ErrorRecord err in PowerShellInstance.Streams.Error)
{
string error = Convert.ToString(err.ErrorDetails) + " " + Convert.ToString(err.Exception.Message) + " " + Convert.ToString(err.Exception.InnerException);
iLogger.PowerShellException(error);
}
}
if (result.Count > 0)
{
return true;
}
}

Simple Dom HTML changes not taken

I use simple_html_dom.php
I want to remove the first child of a element :
The HTML :
<div id="result">
<a class="result_type1" href="#">The title</a>
<span class="item">item</span>
<span class="more">more</span>
<span class="description">description</span>
</div>
The PHP test 1 :
foreach($html2->find("div[id=result]") as $element)
{
$element->children(0)->outertext=$element->children(1)->outertext;
$element->children(1)->outertext=$element->children(2)->outertext;
$element->children(2)->outertext=$element->children(3)->outertext;
$element->children(3)->outertext="";
echo $element->children(0)->plaintext;
}
Result (not good) :
The title
PHP test 2
foreach($html2->find("div[id=result]") as $element)
{
$element->children(0)->outertext=$element->children(1)->outertext;
$element->children(1)->outertext=$element->children(2)->outertext;
$element->children(2)->outertext=$element->children(3)->outertext;
$element->children(3)->outertext="";
echo $element->children(0)->outertext;
}
Result (good):
<span class="item">item</span>
And I don't get the same item.
With plaintext, I get the element that should be removed
It appears that these three properties (outertext, innertext and plaintext) are separated when the information is processed, as stored in a multidimensional array:
If you make a change to an element with "outerText", the other two properties do not change:
element1 plaintext: "text 1",
outerText: "<span> text 2 </ span>",
           InnerText: "text 1"
       
Same if you make a change with "plaintext".
element1 plaintext: "text 2"
            outerText: "<div> text 1 </ div>",
         InnerText: "text 1" .
Only the "InnerText" property affects the other two properties ...
element1 plaintext: "text 2"
           outerText: "<div> text 2 </ div>",
          InnerText: "text 2"                  
by against if you change an element with "href" it will affect "outertext" value.
element1 href : "link2",
           outerText: " ",
Inversly change with "outerText" not influence "href".
element1 href : "link1",
           outerText: " ",

Crystal Reports Configuration Tool [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a Crystal report with 50 odd subreports, each with loads of parameters. Switching it from one database to another takes ages as the Crystal Reports IDE insists that you enter all the parameters for each sub-report.
I'm wondering if it's possible to write a quick tool in C# to view the current database config of all of the sub-reports in an rpt file, and ideally to switch to a different database.
Unfortunately (or fortunately) I don't have much experience of the Crystal object model - anyone know where to start?
Thanks,
Jon.
This should do the job. Obviously replace the passwords and User names where neccesary.
Private Sub ProcessFile(ByVal FileName As String)
Dim CR As Engine.ReportDocument = Nothing
Try
CR = New Engine.ReportDocument
CR.Load(FileName, CrystalDecisions.Shared.OpenReportMethod.OpenReportByDefault)
'Recurse thru Report
RecurseAndRemap(CR)
'Save File
CR.SaveAs("OutPutFilePath")
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
If Not CR Is Nothing Then
CR.Close()
CR.Dispose()
End If
End Try
End Sub
Private Sub RecurseAndRemap(ByVal CR As Engine.ReportDocument)
For Each DSC As CrystalDecisions.Shared.IConnectionInfo In CR.DataSourceConnections
DSC.SetLogon("YourUserName", "YourPassword")
DSC.SetConnection("YouServerName", "YourDatabaseName", False)
Next
CR.SetDatabaseLogon("YourUserName", "YourPassword")
For Each Table As Engine.Table In CR.Database.Tables
Table.LogOnInfo.ConnectionInfo.UserID = "YourUserName"
Table.LogOnInfo.ConnectionInfo.Password = "YourPassword"
Next
If Not CR.IsSubreport Then
For Each SR As Engine.ReportDocument In CR.Subreports
RecurseAndRemap(SR)
Next
End If
End Sub
Hope that helps Cheers Ben
In VB6 we use something like next (dirty copy-paste form old code, incrementally updated from CR6 to CR9), maybe you can get some ideas:
For Each tmpTable In Report.Database.Tables
Set CPProperties = tmpTable.ConnectionProperties
CPProperties.DeleteAll
CPProperties.Add "Provider", "SQLOLEDB"
CPProperties.Add "Data Source", mServerName
CPProperties.Add "Initial Catalog", mBaseName
CPProperties.Add "User ID", mUserID
CPProperties.Add "Password", mPassword
CPProperties.Add "Server Name", mServerName
CPProperties.Add "Server Type", "OLEDB"
CPProperties.Add "DataBase", mBaseName
tmpTable.SetTableLocation tmpTable.Location, "", ""
Next tmpTable
For Each tmpSection In Report.Sections
For Each tmpObject In tmpSection.ReportObjects
If TypeName(tmpObject) = "ISubreportObject" Then
Set tmpReport = tmpObject.OpenSubreport()
For Each tmpTable In tmpReport.Database.Tables
Set CPProperties = tmpTable.ConnectionProperties
CPProperties.DeleteAll
CPProperties.Add "Provider", "SQLOLEDB"
CPProperties.Add "Data Source", mServerName
CPProperties.Add "Initial Catalog", mBaseName
CPProperties.Add "User ID", mUserID
CPProperties.Add "Password", mPassword
CPProperties.Add "Server Name", mServerName
CPProperties.Add "Server Type", "OLEDB"
CPProperties.Add "DataBase", mBaseName
tmpTable.SetTableLocation tmpTable.Location, "", ""
Next tmpTable
End If
Next tmpObject
Next tmpSection
Bit of experimentation seems to solved the problem:
private void Form1_Load(object sender, EventArgs e)
{
ReportDocument rd = new ReportDocument();
rd.Load("Report.rpt");
Explore(rd);
foreach (ReportDocument sr in rd.Subreports)
{
Explore(sr);
}
}
private void Explore(ReportDocument r)
{
foreach (IConnectionInfo con in r.DataSourceConnections)
{
if (!r.IsSubreport)
Console.WriteLine("Main Report");
else
Console.WriteLine(r.Name);
Console.WriteLine(con.DatabaseName);
Console.WriteLine("-");
}
}