|
I'm changing ISP's in a week or so, so I resurrected an old app I wrote to monitor my ISP and tell me when it changed.
And it didn't work any more, because the IP Geolocation service I was using has changed and needs an API signup instead of presenting the data as CSV.
So, I thought I'd re-write it using HtmlAgilityPack.
But it was odd that I got no error message in the original code ... until I spotted this:
private void FillInDetails(string host)
{
Timestamp = DateTime.Now;
IPAddress addr = IPAddress.None;
try
{
using (WebClient wc = new WebClient())
{
if (string.IsNullOrWhiteSpace(host))
{
host = "http://freegeoip.net/csv";
}
else
{
host = string.Format("http://freegeoip.net/csv{0}{1}", "/", host);
}
string data = wc.DownloadString(host);
string[] sections = BreakCSVLine(data);
if (sections.Length != freegeoipDataSectionsCount) throw new ArgumentException("Data returned from FreeGeoIP has changed format!");
addr = IPAddress.Parse(sections[freegeoipDataAddress]);
CountryCode = sections[freegeoipDataCountryCode];
Country = sections[freegeoipDataCountry];
RegionCode = sections[freegeoipDataRegionCode];
Region = sections[freegeoipDataRegion];
City = sections[freegeoipDataCity];
Zipcode = sections[freegeoipDataZipcode];
TimeZone = sections[freegeoipDataTimeZone];
Area = sections[freegeoipDataArea];
float lat = float.Parse(sections[freegeoipDataLatitude]);
float lon = float.Parse(sections[freegeoipDataLongditude]);
LatLong = new PointF(lon, lat);
}
}
catch (Exception)
{
}
Address = addr;
}
So I carefully create my own exception to tell me why it's not working ... and then explicitly ignore it.
I do wonder about past-me's thought processes sometimes ...
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Exception handling/reporting is something I've never figured out how to do well, especially when writing a web application. The back-end throws an exception. What do you do? Log it somewhere nobody ever looks, least of all me? Do you report it to the front-end?
The front-end has to deal with the back-end exception. What do you do? Display an obtuse message to the user?
The front-end itself generates an exception. Is it even caught? What do you do? Another obtuse message? Or an API endpoint that it calls to log it on the server in a log that no one, least of all me, ever looks at?
I've decided to take a rather drastic approach to very specific problems (like a failure to update an audit table) - I email myself the exception and filter it in Outlook into specific folders. I find it a lot more effective in knowing about the exception and to fix it.
|
|
|
|
|
I feel your pain!
Been struggling with this myself.
I always make sure my users know something went wrong.
Like really wrong.
They should get an exception and not be able to continue.
Preferably some "scary" message that sounds very technical.
Very user unfriendly, but at least they'll call me so I can fix the issue instead of ignoring the error and continuing with potentially corrupt data (yes, that happened in the past)
|
|
|
|
|
Beyond that Exception , what's that:
OriginalGriff wrote: host = string.Format("http://freegeoip.net/csv{0}{1}", "/", host); Why do you need a parameter for the constant value of "/" ?
My diagnosis:
A severe case of hypocaffeinaemia.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
I was thinking about the SSD in my wife's laptop. 120GB and it's been running for 4-5 years.
Kind of fell down a rabbit hole...
A Windows App?: Not really
I started looking for apps to tell me the situation.
Found an article that explains some things:
Find out how much longer your SSD will last - CNET[^]
The article mentions this app: Crystal Disk Mark -- not great[^]
All Comes Down to Reads & Writes
Basically the article tells you that most likely it will take you 15 years to wear a good SSD out so don't worry too much.
Found Some Sample Code
Then I found a sample program that makes some API calls and tells you how many bytes you've read and written since the OS was started.
Here's the output for my wife's computer that has been running for over 16 days without rebooting:
http://i.stack.imgur.com/3jTsD.png[^]
Compare those read/write bytes to mine that has only been running[^] for a little over 2 hours.
Here's the code (alterations by me) from c++ - How to get global Windows I/O statistics? - Stack Overflow[^]
NOTE: hard-coded to check only the C:\ drive
Update: Updated method to display the number of days computer has been running.
#include <windows.h>
#include <iostream>
#include <locale>
#include <sysinfoapi.h>
std::__cxx11::string displayValue(LONGLONG);
void getOsRunTime();
int main() {
HANDLE dev = CreateFile(LPCSTR("\\\\.\\C:"),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
DISK_PERFORMANCE disk_info { };
DWORD bytes;
if (dev == INVALID_HANDLE_VALUE) {
std::cerr << "Error opening disk\n";
return 1;
}
if (!DeviceIoControl(dev,
IOCTL_DISK_PERFORMANCE,
NULL,
0,
&disk_info,
sizeof(disk_info),
&bytes,
NULL))
{
std::cerr << "Failure in DeviceIoControl\n";
return 1;
}
std::cout << "Bytes read: " << displayValue(disk_info.BytesRead.QuadPart) << "\n";
std::cout << "Bytes written: " << displayValue(disk_info.BytesWritten.QuadPart) << "\n";
getOsRunTime();
}
std::__cxx11::string displayValue(LONGLONG byteCount){
auto s = std::to_string(byteCount);
int n = s.length() - 3;
while (n > 0) {
s.insert(n, ",");
n -= 3;
}
return s;
}
void getOsRunTime(){
ULONGLONG milli = GetTickCount64();
long days = milli / (3600000 *24);
milli = milli - (3600000 *24) * days;
long hr = milli / 3600000;
milli = milli - 3600000 * hr;
long min = milli / 60000;
milli = milli - 60000 * min;
long sec = milli / 1000;
milli = milli - 1000 * sec;
std::cout << "OS has been running " << days << " days " << hr << " hours " << min << " minutes " << sec << " seconds " << milli << " ms." << std::endl;
}
modified 27-Mar-21 23:50pm.
|
|
|
|
|
What ARE you guys doing? Writing over 1GB/hr!
My linux laptops (not doing a lot, I admit) are running much much less than that.
(sorry I had a bit of a hiccup getting reliable stats. I'll update a bit later.)
Installing Audacity on one (and running it a bit) put a 150MB/50MB lump in its stats.
Cheers,
Peter
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
modified 27-Mar-21 22:24pm.
|
|
|
|
|
Peter_in_2780 wrote: What ARE you guys doing? Writing over 1GB/hr!
I know. It's crazy on Win10. I run Win10 on this new laptop but I run Ubuntu 20.04 on my main desktop that I use daily and it performs so much better than win10.
Win10 reads and writes to disk constantly. Check it out. Here's an updated snapshot of what my laptop has done since that last one[^]. I haven't even been on this laptop for hours now, but it's written another 1.1GB and read another 1GB.
I noticed this with Win10 when it first came out because I could no longer run an HDD -- win10 eats so much I/O that the machine would get overwhelmed. Had to switch to SSDs or win10 kills performance.
|
|
|
|
|
How much memory do you have on the box? If 8 GB or less, probably doing a lot of swapping to disk as part of the figures you are seeing.
|
|
|
|
|
|
Is std::__cxx11 a GCC-only namespace? I've never seen it used in Visual Studio, and it gives an error.
|
|
|
|
|
It probably is. My C/C++ skills are very rusty and I was just trying the quickest way to return a string and found that type. Sorry for the inconvenience.
I didn't want to install Visual Studio on my machine so I'm using Visual Studio Code and MinGW.
I kind of blindly stumbled my way through to get that code working.
David O'Neil wrote: Is std::__cxx11 a GCC-only namespace?
|
|
|
|
|
 Here's a version without the GCC specific code, and a more C++ approach to the thousands separator (not that I care for that - I always have to look it up and it is a pain).
For those who use it, you will need to set your project to Multi-byte.
#include <windows.h>
<h1>include <iostream></h1>
<h1>include <locale></h1>
<h1>include <sysinfoapi.h></h1>
void getOsRunTime();
struct threes : std::numpunct<char> {
std::string do_grouping() const { return "\3"; }
};
int main() {
HANDLE dev = CreateFile(LPCSTR("\\\\.\\C:"),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
DISK_PERFORMANCE disk_info { };
DWORD bytes;
if (dev == INVALID_HANDLE_VALUE) {
std::cerr << "Error opening disk\n";
return 1;
}
if (!DeviceIoControl(dev,
IOCTL_DISK_PERFORMANCE,
NULL,
0,
&disk_info,
sizeof(disk_info),
&bytes,
NULL))
{
std::cerr << "Failure in DeviceIoControl\n";
return 1;
}
std::cout.imbue(std::locale(std::cout.getloc(), new threes));
std::cout << "Bytes read: " << disk_info.BytesRead.QuadPart << "\n";
std::cout << "Bytes read: " << disk_info.BytesRead.QuadPart << "\n";
std::cout << "Bytes written: " << disk_info.BytesWritten.QuadPart << "\n";
getOsRunTime();
}
void getOsRunTime(){
ULONGLONG milli = GetTickCount64();
long days = milli / (ULONGLONG)(3600000 *24);
milli = milli - ((ULONGLONG)3600000 *24) * days;
long hr = milli / 3600000;
milli = milli - (ULONGLONG)3600000 * hr;
long min = milli / 60000;
milli = milli - (ULONGLONG)60000 * min;
long sec = milli / 1000;
milli = milli - (ULONGLONG)1000 * sec;
std::cout << "OS has been running " << days << " days " << hr << " hours " << min << " minutes " << sec << " seconds " << milli << " ms." << std::endl;
}
|
|
|
|
|
That's great stuff. Thanks for sharing. I also cleaned up the code and made it so you can provide a drive letter (just the letter) as a command-line arg and it will scan the drive.
Unfortunately I couldn't get it quite right for mapped drives, there is something odd there.
Also I now use std::string as I should.
You can get the code at my github repo: GitHub - raddevus/wearlevel: wearlevel project that checks 1) how long OS has been running, 2) how many bytes read and written during uptime.[^]
Also, here's one more thing. I put a micro sd card in the laptop slot and ran it on d:
c:\>wearlevel d
See the snapshot[^].
Interesting that windows writes 61,440 bytes to the newly attached drive.
And, oh yeah, 61440 / 4096 = 15. But I have no idea why or what that means. 
modified 28-Mar-21 18:57pm.
|
|
|
|
|
It seems the rate of change in our industry is increasing. I am worn out with trying to keep up.
I am stronger than I think I am. I am smarter than I think I am. I am better than I think I am. - anon.
|
|
|
|
|
Never tried to keep up. Early adoption is costly.
|
|
|
|
|
The pattern I see regularly is:
There's this amazing new way of doing things call FrogrooAPI and the code is open source.
One week later - we need to also download CatrooAPI for FrogrooAPI to work.
Six months later - so as long as you have FrogrooAPI, CatrooAPI, MouserooAPI, GerbilrooAPI and DogrooAPI everything should work...
“That which can be asserted without evidence, can be dismissed without evidence.”
― Christopher Hitchens
|
|
|
|
|
Reaching for Private Parts - The Daily WTF[^]
Modifying a class using reflection only in production...
What do you get when you cross a joke with a rhetorical question?
The metaphorical solid rear-end expulsions have impacted the metaphorical motorized bladed rotating air movement mechanism.
Do questions with multiple question marks annoy you???
|
|
|
|
|
Why, just yesterday, I wrote an extension method which fiddles about in the private parts of a .net class.
This is how it's done when Microsoft makes things too elephanting rigid.
The alternative would be to reinvent this particular wheel, which would very likely kill performance.
|
|
|
|
|
PIEBALDconsult wrote: I wrote an extension method which fiddles about in the private parts of a .net class.
There may be (extremely rare) cases when such perversions may be necessary, but a difference in behaviour between development and production?!
Isn't the whole idea of a development environment to be as close as possible to the production environment, but without changing production data?
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Shouldn't there be a test database (recent copy of the production database) to test code against?
|
|
|
|
|
I've developed frameworks, and it's virtually impossible to anticipate all user requirements. At least I was dealing with in-house frameworks, where it was easy to interact with users and quickly respond to their needs. For the kind of things that Microsoft is providing, I'm not at all surprised that what you're doing is occasionally necessary.
|
|
|
|
|
Greg Utas wrote: I've developed frameworks, and it's virtually impossible to anticipate all user requirements.
This is the fundamental flaw with all frameworks. Despite it's name the dotNet Framework isn't so much a framework as it is a collection of useful and related classes. It's more of an OS level API for most programmers.
|
|
|
|
|
Another flaw with frameworks is a monotonic increase in their surface-to-volume ratio. It stems from a reticence to introduce "breaking changes" when evolving the framework, because existing users who want to migrate to the next major release think it should be transparent. I have no sympathy for them.
To me, a framework embodies a powerful object model, which means that it must typically be used as a whole, whereas a library is a collection of disparate classes whose collaborations are up to the user.
|
|
|
|
|
One of the reasons I keep falling in love with C++ over and over again is
A) source level polymorphism
B) selective linking
leading to
C) Frameworks that aren't frameworks as long as they aren't coded like garbage
What I mean is you can have a bunch of things that all work together (the STL, a framework more than a library considering how many different things it covers, but all the core bits are used together) and you can only include bits you need.
This encourages me to code even things that may be used rarely, because if you don't need it it's never compiled in.
That leads to very little framework bloat. Plus it's as modular as you develop it to be. If you update <iostream> library you can theoretically, simply update that header as long as you don't change exiting source level interfaces
Real programmers use butterflies
|
|
|
|
|
Please elaborate. I think I might learn something.
Source level polymorphism? Never heard of source level as an adjective for polymorphism. What's it mean?
Selective linking? By this, do you mean that code that isn't used doesn't get linked into the .exe?
I see the STL as being in a half-world between library and framework. Iterators, for example, cut across many of the classes, but the higher-level classes stand on their own. That's quite different from what I'm doing, where it's impossible to use any component on its own, because those in the same static library use each other freely. When I read about this dependency injection fetish in light of what I'm doing, I just throw up my hands and chortle at the endless boilerplate that would be needed. Besides, toy test harnesses will never exercise a framework as well as a few serious applications.
|
|
|
|