|
Krischu wrote: Is there a tool that can achieve this? If there is then Google is the place to find it.
Krischu wrote: do I have to write it myself?
If there isn't an existing tool then yes.
|
|
|
|
|
For those that don't know, GLR parsing is some of the most powerful parsing there is. It can even parse *natural language constructs* - like, wow.
The algorithm involves some formidable math(s) but I found a GLR parser in C#
GitHub - jcoder58/GLRSharp: GLR Combinatorial Parser written in C# 4.0[^]
This is super cool. It's only downsides are it detects errors later than say, an LR(0) parser, and it isn't as intuitive as LL parsing + you can't do downward inheritance with it because it's not top-down, it's bottom up. Still, that's not such a big deal.
GLR is the holy grail of context-free language parsing.
Real programmers use butterflies
|
|
|
|
|
So my big hangup on writing visual dev code (see flowstone) or workflow code is UI stuff.
Well look what i found:
GitHub - dataweb-GmbH/NShape[^]
An open source diagrammer library for industrial apps in C#
woo. it's christmas in february!
Real programmers use butterflies
|
|
|
|
|
nice one
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
|
It's interesting but it looks like an app, not a library. I wanted to add diagramming to my own apps. Turns out this tool i found isn't all i hoped it was though.
Real programmers use butterflies
|
|
|
|
|
|
Holy crap i think so. Nice find. Thanks, and Mark wrote it even.
Real programmers use butterflies
|
|
|
|
|
Welcome, always glad when we can recommend one of our own!
Marc is a very talented person.
I'm hiding from exercise...I'm in the fitness protection program.
JaxCoder.com
|
|
|
|
|
There is one thing I really liked in the 1990s - debugging with the symantec IDE for C++. It had those cool step forward/step backward features in the debugger. Dont know why this was never added to other IDEs but its a really, really useful thing.
Now someone did exactly that, and even more: RevDeBug (find it on VS Marketplace or .com) is a free extension that allows you to track all state changes, record them, and then travel back and forward seeing visualy the changes. And it also tracks handled and unhandled exceptions, so you can just trace backwards from any exception what led to it.
Worth trying it out. Seems to work for most .NET languages.
forging iron and new ideas
|
|
|
|
|
There is also WinDbg which supports "time travel" though I have yet to master it
|
|
|
|
|
|
Introduction
I initially pulled this from the internet over a decade ago and had to open it back up when my client didn't want to use SMSS. I gave him the option to backup and restore his SQL Server with a few mouse clicks.
Background
My client was too cheap to purchase a real backup/restore SQL Server application so I created/enhanced this to enable him to do it with just a few mouse clicks.; If you would like to enhance the code and collaborate on potential enhancements you can download the code from git hub here https://www.github.com/CTBlankenship/BackupRestore_Source
Using the code
There are a few things you need to do to get this to work for you. The first is directory definitions:
1. A scratch pad area where the .bak file is copied prior to being compressed and copied to the destination directory. There should never be a .bak file in this directory since it is deleted after it is used to create a .zip file
2. The location of your SQL Server database and log files (.ldf and .mdf)
3. The location directory where you want to store the compressed .bak files (which are now zip files)
Secondly, edit the main form code behind to specify a connection string for the application. I've keyed the connections to recognize machine names. So, when I copy the app to my client's machine it knows that connection string for that implementation ... another for when I'm working with it on my development machine.
Third, edit the main form code behind to filter the available databases so that he sees only the databases that apply to his application and keep all of the other ones hidden so he doesn't make a mistake with any databases other then his own.
To backup a SQL Server select the database to backup and press the Backup button. This backs up the database and stores its .bak file in the Scratch directory where .NET compression is used to compress it. The .bak file is compressed into a .zip file and copied to the directory you specifiy within the app.config file. I set mine up so that it is copied to by Google Drive so it is synched with offsite storage.
To truncate the log file select the desired database and press the Shrink Log File
To restore a database select the desired .zip file (the file is named using month day year hour minue and second). It then provides a warning message that identifies the age of the file (in hours) and asked if he really wants to restore from that particular .zip file. The .zip file is then decompressed into the Scratch subdirectory. From there script is written to backup the database from the .bak file as expected. The .back file is then deleted leaving the Scratch directory empty for the nex round of processing.
I added logging which you can view using he Show button. This is helpful since I store the SQL script used to both backup and restore the database. If there is ever a failure it is a simple step to copy the script, drop it into a new query window in SSMS, run it and try and determine where the script failed and why.
To clear the log file simply delete it from the application's startup directory. I tried to make clearing the log as an option available through the interface but for some reason, the file remained "open" and accessing it from the next round of logging errored out with an I/O error saying the file is open by another process. One of you might be able to figure that out and make it possible to clear the file without accessing the file with File Explorer. Seems trivial as I type this out but the solution evaded me and I gave up ... I've spent too much time on this as it is.
One glaring problem with this utility is that it demands the use of Version 11 of the Microsoft.SqlServer.Management.Sdk.Sfc file. I've discovered that if the only database you have installed on your server is 2016 or better, the only version of this file available is 12+. I had to hack my GAC so I could copy the Version 11 file and install it to the GAC on my client's machine. Version 11 is automatically installed with SQL Server 2012. If any of you gurus could figure this out that would be grand.
I work alone so I figured I'd use you fellows to view it and perform a "code review". Enchance it until your heart is content and the push the changes to github.
The drawbacks to this program is that it currently only has an option for a full backup. Obviously this is not optimal since if there is a problem the only option is to loose as much data that was entered since the last full backup. I tried to get him to purchase a "real" SQL Backup utility but he's a cheap dude. Plus, he NEVER backed the database currently being used by the system that I'm replacing.
Have at it ... I've had fun now it is time for a few of you to add your own personal genius to the application. So, that said, it would be cool to be able to include this form in the utilities section of my app. However, the users do not have NETWORK SERVICE credentials to the SQL Server so they cannot specify the network drive mapping, 2) allow the user to configure the a job as a windows service so it can be scheduled on a periodic basis. There is a free application out there that does all of this and more but I obviously cannot integrate it into my own app though so I'll keep this around for a while.
Cheers,
Charles T. Blankenship
Points of Interest
Thanks to all of you that contribute ... be gentle now.
|
|
|
|
|
You now have this posted as an Article, a Tip, and now here. One place only is the accepted protocol.
|
|
|
|
|
More exactly, it allows to create a .mkv file from any video file, choosing which streams to include in the process.
mkv is a container format which allows to have as many streams (video, audio, subtitles, chapters, etc...) as needed. Each stream localization can be specified.
The name of this suite is mkvtoolnix.
The website is here^.
The suite for Windows can be downloaded from here^.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
For those who may be interested, particularly .NET developers, I have published three (free) components to NuGet that could be useful to you. Documentation (README.md) is included in the folder to which your NuGet package manager deploys it.
JHelpers
JLogger
JDAC
As requested, here are the descriptions of the NuGet packages. I will post the entire README.md files' content as replies to this post.
modified 17-Jul-19 18:30pm.
|
|
|
|
|
It would help if you actually told us what these tools do.
|
|
|
|
|
I’ll do just that as soon as I get to my computer. However, the links take you to the NuGet page for the selected component, which has a description of what they do.
Thanks for the feedback.
|
|
|
|
|
JHelpers
========
JHelpers is a .NET Standard 2.0 library component that can be used with any .NET
project, whether Core or Standard, on any supported OS to access SQL Server. It
is a library of generally useful methods and functionality that can save a
developer from writing code to accomplish these mundane tasks – or worse, have
several versions of a method that does the same thing written in multiple
places. JHelpers is used in my JDAC and JLogger NuGet packages for that very
reason.
ContextMgr
----------
ContextMgr is a thread-safe singleton that can be used to store data in a single
place accessible from anywhere, and any thread, in the application. One typical
use is to store settings and other runtime values so their sources (file,
database, etc.) only have to be read once. Anything that can be defined as a
unique String name and a value or reference type of any kind can be kept there.
Values are added as a String key name (which must be unique) and any value or
reference type, boxed as a dynamic type.
ContextMgr has no initialization, and as a singleton, does not use “new” to be
created. The actual instance is dynamically created on the first reference in
the code.
Code Example
Boolean retVal = false;
ContextMgr.Instance.ContextValues.Add("Computer Name", Environment.MachineName);
ContextMgr.Instance.ContextValues.Add("Startup Time", DateTime.Now);
IPAddress[] ips = Dns.GetHostAddresses("BubbaComputer");
ContextMgr.Instance.ContextValues.Add("IP Addresses", ips);
dynamic machineName = "";
retVal = ContextMgr.Instance.ContextValues.TryGetValue("Computer Name", out machineName);
dynamic startupTime = "";
retVal = ContextMgr.Instance.ContextValues.TryGetValue("Startup Time", out startupTime);
dynamic hostAddresses = null;
retVal = ContextMgr.Instance.ContextValues.TryGetValue("IP Addresses", out hostAddresses);
In your application’s shutdown code, I recommend adding this line so the
ContextMgr disposes of its resources without waiting on the .NET garbage
collector.
ContextMgr.Instance.Dispose();
CommonHelpers
-------------
This is a static class with a number of useful static methods.
### Extension Methods
String GetFullExceptionMessage(this Exception ex2Examine, Boolean getDataCollection, Boolean getStackTrace)
This Exception object extension returns error messages from the parent exception
and any exceptions down the stack, and optionally, the data collection. The
Exception.Data collection is used to store name-value pairs that typically
record runtime values or other significant data for debugging.
Boolean Contains(this String source, String toCheck, StringComparison strComp)
This String object extension allows string comparison type on the string to
check. The extension method returns true if it the toCheck string is in the
source string, false if not.
Int32 ContainsHowMany(this String source, String toCheck, Boolean ignoreCase = false)
This String object extension gets the count of how many times a give string
occurs within another string. The extension method returns a Count of 0 to n
occurrences.
Boolean ConvertToBoolean(this String valueToExamine, out Boolean isBoolean)
This String object extension to convert a string, assumed to be in a format that
can be converted, to a Boolean value. Recognizes as true (case insensitive)
true, on, yes, up, ok, good, 1, -1. Recognizes as false (case insensitive):
false, off, no, down, not ok, bad, 0. If the conversion fails, false is
returned. Check the isBoolean out value to see if the conversion detected a
Boolean value. If it is false, the value was not converted.
Boolean IsBoolean(this String valueToExamine)
This String object extension tests a string, assumed to be in a format that can
be converted, to a Boolean value. Recognizes as true (case insensitive) true,
on, yes, up, ok, good, start, 1, -1. Recognizes as false (case insensitive):
false, off, no, down, not ok, bad, stop, 0. If the conversion fails, false is
returned. Otherwise, true is returned.
Boolean IsOnlyDigits(this String testString, Boolean includePeriod = false)
This String object extension checks for all characters being digits. Conversion
functions to test numbers may translate letters as Hex values. includePeriod is
set to true if the one and only period is to be treated as being a number, so
that decimal number strings can be handled properly.
String GetOnlyDigits(this String testString, Boolean includePeriod = false)
This String object extension gets all digits in a string and ignores any
non-digits. If includePeriod is true, then the first period in the string will
be included in the results.
String GetOnlyLetters(this String testString, Boolean includeSpace = false)
This String object extension gets all letters in a string and ignores any
non-letters. However, if includeSpace is true, then any spaces found are
included in the return value.
String GetOnlyLettersAndDigits(this String testString, Boolean includePeriodAndSpace = false)
This String object extension gets all letters and digits in a string, and
ignores all else, with the exception of periods and spaces when
includePeriodAndSpace is true.
Boolean IsOnlyLetters(this String testString, Boolean includeSpace = false)
This String object extension checks for all characters being letters. If
includeSpace is true, then spaces are accepted as if they were letters.
Boolean IsOnlyLettersAndOrDigits(this String testString, Boolean includePeriodAndSpace = false)
This String object extension checks for all characters being only letters and
numbers. If includePeriodAndSpace is true, then all periods and spaces are
treated as if they are letters.
Boolean IsEmailFormat(this String email)
This String object extension checks the string to see if it is a valid email
format. It does not check whether it is a valid, working email.
DateTime GetDateTime(this String dateString, DateTime dateDefault)
This String object extension converts string to date, or returns the default
value.
Decimal GetDecimal(this String numberString, Decimal decimalDefault)
This String object extension converts string to decimal value, or returns the
default value.
Int32 GetInt32(this String numberString, Int32 integerDefault)
This String object extension converts string to an Int32 value, or returns the
default value.
Int64 GetInt64(this String numberString, Int64 integerDefault)
This String object extension converts string to an Int64 value, or returns the
default value.
Object GetDefaultValue(this Type t)
Generic extension method that returns a default value for the type, if one
exists. This is useful in generic instances where default\<t\> may not work.
### Helper Functions and Properties
#### Enum
DistanceUnitsOfMeasureEnum
Unassigned = 0,
Miles = 1,
Kilometers = 2,
Feet = 3,
Meters = 4
This is used with geolocation to specify the units of measure for distance.
#### Class
AddressGeoData
Double Latitude1
Double Longitude1
Double Altitude1
Double Latitude2
Double Longitude2
Double Altitude2
Double LinearDistance (value is calculated, not set)
DistanceUnitsOfMeasureEnum UnitsOfMeasure;
##### Class Constructor
AddressGeoData(Double pLatitude1, Double pLongitude1, Double pAltitude1, Double pLatitude2, Double pLongitude2, Double pAltitude2, DistanceUnitsOfMeasureEnum pUnitsOfMeasure)
##### Class Methods
void SetUnitsOfMeasure(DistanceUnitsOfMeasureEnum lngUnitsOfMeasure)
void SetLinearDistance(Double dDistance)
This class is used to store two geolocations specifying the latitude, longitude,
and altitude. The units of measure determine the units corresponding to the
LinearDistance value. Altitude may be 0 if not known or not wanted.
String RowDelimiter (Get only)
This value can be applied to the value for a constant. RowDelimiter is the same
non-printable ASCII character used in teletypes and other devices to indicate a
new row, and not likely to be seen in string data.
String ColumnDelimiter (Get only)
This value can be applied to the value for a constant. ColumnDelimiter is the
same non-printable ASCII character used in teletypes and other devices to
indicate a new column, and not likely to be seen in string data.
String TableDelimiter (Get only)
This value can be applied to the value for a constant. TableDelimiter is the
same non-printable ASCII character used in teletypes and other devices to
indicate a new table of data, and not likely to be seen in string data.
String FullComputerName (Get only)
Gets the full computer name that DNS will recognize in any domain
String GetDNSName(String pComputerName = "")
Gets the DNS host entry table name for a given computer name. Pass in any
computer name. If left blank or null, the current computer name will be used.
String CurDir (Get/Set)
Gets or sets the fully qualified path of the current working directory. For
services, the current directory via normal means shows the Windows System32
directory because the service runs under an exe located there. This property
accounts for that by using one method call for running in the IDE, and another
for running compiled.
Boolean AmIRunningInTheIDE (Get only)
This method will return true if this project, or any project that calls this
component as compiled code, is running under the IDE. This method returns false
if no IDE is being used.
Boolean IsInDomain()
Returns true if the computer running the code is in a domain. False if it is
not.
String GetComputerDomainName()
Returns the Domain which the computer is joined to. Note: if user is logged in
as local account the domain of computer is still returned. Returns a String with
the domain name if it's joined, or an empty String if it isn't.
String GetFullComputerDomainName()
Returns the full domain name instead of the alias.
Boolean IsDaylightSavingsTime(DateTime dtmToTest)
True if the datetime supplied falls within the period of Daylight Savings.
Boolean IsDaylightSavingsTime()
True if it is currently daylight savings time.
String CurrentTimeZoneDaylightName (Get only)
Name of the current time zone for daylight savings.
String CurrentTimeZoneName (Get only)
Name of the current time zone, regardless of daylight savings.
Int32 Asc(String strChar)
Same functionality as the VB6 ASC function - give it a character, get back the
ASCIII decimal number.
String Hex(Int32 lngValue)
Same as the VB6 function. Converts a 32 bit integer to a String hex value.
Int32 GetCurrentCPUUsage()
Gets the current % processor time
Int32 AvailableRAMinMB()
Returns available RAM MBs
PingReply Ping(String strHostName, Int32 lngTimeout)
Pings the specified server. Returns a PingReply instance indicating whether or
not the operation was successful.
void GetLinearDistances(ref List<AddressGeoData> objAddressList)
This function uses the Haversine formula to calculate linear distance between
two sets of latitude and longitude, with an adjustment for the earth's radius
based on the latitude. Haversine is used instead of Vincenty’s formula to keep
the computation simpler and less processor intensive. This function takes a List
of address geo data instances and processes them, updating the individual class
instances in the List for the linear distance property.
Double GetLinearDistance(double Latitude1, double Longitude1, double Altitude1, double Latitude2,
double Longitude2, double Altitude2, DistanceUnitsOfMeasureEnum lngUnitsOfMeasure)
This function uses the Haversine formula to calculate linear distance between
two sets of latitude and longitude, with an adjustment for the earth's radius
based on the latitude. Haversine is used instead of Vincenty’s formula to keep
the computation simpler and less processor intensive. This overload allows the
caller to specify what units of measure is desired for the return value.
Double GetLinearDistance(Double Latitude1, Double Longitude1, Double Altitude1, Double Latitude2, Double Longitude2, Double Altitude2, Boolean UseMiles)
This function uses the Haversine formula to calculate linear distance between
two sets of latitude and longitude, with an adjustment for the earth's radius
based on the latitude. Haversine is used instead of Vincenty’s formula to keep
the computation simpler and less processor intensive. This overload allows the
user to choose between miles and kilometers (UseMiles param)
Double GetLinearDistance(Double Latitude1, Double Longitude1, Double Latitude2, Double Longitude2,
DistanceUnitsOfMeasureEnum UnitsOfMeasure)
This function uses the Haversine formula to calculate linear distance between
two sets of latitude and longitude, but without providing altitude (all
calculations assume linear over the curve of the earth at sea level) with an
adjustment for the earth's radius based on the latitude. Haversine is used
instead of Vincenty’s formula to keep the computation simpler and less processor
intensive. This overload allows the user to choose what unit of measure.
Double RadianToDegree(Double Coordinate)
Converts radians to degrees
Double CelciusToFahrenheit(Double DegC)
Converts Celsius to Fahrenheit
Double FahrenheitToCelsius(Double DegF)
Converts Fahrenheit to Celsius
String StringToBase64(String String2Convert)
Convert String to Base64
String Base64ToString(String ByteString64)
Convert Base64String to String
List<ManagementObject> GetNetworkPrinters()
Gets a list of network printers using one ManagementObject instance per printer
in a List object.
void SetIntBitValue(ref Int32 intValue, Int32 bitPlaceValue, Boolean setBitOn)
Helper method to set bit value of an Int on/off.
Boolean GetIntBitValue(Int32 intValue, Int32 bitPlaceValue)
Helper method to get the state of a bit value of an Int.
String GetStackInfo()
This gets the module, function, line number, and column number info in a String.
This is useful when logging and creating exceptions to define exactly where
something occurred.
String GetStackInfo(Exception ex)
This gets the module, function, line number, and column number info in a String
based on an exception. This is useful when logging and creating exceptions to
define exactly where something occurred.
String GetFullDateTimeStampForFileName(DateTime dtmDate)
This returns a String with a consistent datetime format for a filename.
Boolean IsFileText(out Encoding lngEncoding, String strFileName, Int32 lngNumCharactersToRead)
Detect if a file is text and detects the encoding.
Int32 GetTotalHDDFreeSpace(String pDriveName)
Returns MB of free disk space
Int32 GetTotalHDDSize(String pDriveName)
Returns MB of total space
Int32 GetMinPasswordLength()
Returns the minimum password length from a domain, if one exists. If no domain
exists, -1 is returned.
Boolean IsIPAddress(String pValue, out IPAddress pIPValue)
Checks to see if a string is an IPv4 or IPv6 address, and returns an IPAddress
object as an out parameter.
String AssemblyTitle (Get only)
Title of the .NET assembly.
String AssemblyVersion (Get only)
Version of the .NET assembly.
String AssemblyDescription (Get only)
Description of the .NET assembly.
String AssemblyProduct (Get only)
Product description of the .NET assembly.
String AssemblyCopyright (Get only)
Copyright string used by the .NET assembly.
String AssemblyCompany (Get only)
Company that owns the .NET assembly.
Boolean WriteToLog(String logFileName, String mainMessage, String secondMessage)
Method that performs a log write where the file is tab delimited and has a
column header line.
|
|
|
|
|
This is more like a full article. I really meant just give a brief overview of what each app does, so people can decide whether they need or want to read the full description.
|
|
|
|
|
JLogger
=======
Overview
--------
JLogger is a singleton component as a .NET Standard 2.0 library component that
can be used with any .NET project, whether Core or Standard, on any supported OS
to access SQL Server.
JLogger has these characteristics:
- Multithreaded use – As a singleton, it is accessible from any thread, and
uses locking techniques to ensure there are no collisions.
- High throughput – if the log is being used by many threads concurrently, the
log writes do not stop the calling thread. JLogger uses a first-in,
first-out (FIFO) queue where log writes are put in a queue and written to a
file in a separate thread, concurrently in the background. The WriteDebugLog
command takes the parameters, creates the log data, puts it in a queue. None
of those steps are blocking.
- Send an Email – A debug log write can optionally send an email (SMTP
configuration data required)
- Multiple Log Entry Types – there are several log entry types to choose from.
What they each mean is up to the user writing the code. Some log types are
reserved for the component, and would be ignored in processing the log
entry. These are detailed below.
- New Log File each Day – after midnight, a new log file is created so log
files are named to show the date and time span the log was active.
- Log Retention – logs are automatically removed after the specified number of
days, unless zero is specified, in which case no log files are deleted.
- Tab-delimited Log File – the log is written as a tab-delimited file. This
enables opening up the file in programs like Excel for analysis.
LOG_TYPE Enum
-------------
The enum contains values for the types of logs, and for how the logs are created
and managed.
### LOG_TYPE Values for Logging
Unspecified - Used as a default value until an assignment is made.
Flow – Used to denote a log entry that can be used to trace program flow in the
log.
Error – Used to denote serious exceptions that generally require follow-up and
fixing.
Informational – Denotes the log entry is for information only.
Warning – Means the log entry is warning about a potentially serious condition.
System – Log entry relates to system data.
Performance – Log entry that usually shows elapsed time (as placed in the log
message by the coder) and/or start time.
Test – Used to indicate the log entry was intended for test results.
SendEmail – Used in the WriteDebugLog LOG_TYPE variable to specify that this log
entry should also send an email. The email is only sent if the same flag is used
in Log Management. Use of this flag here only applies to the specific log entry,
not the entire log.
Database - Log entry related to database operations
Service - Log entry related to service operations
Cloud - Log entry related to cloud operations
Management - Log entry related to management concerns or operations
Fatal - Log entry related to some fatal operation or state
Network - Log entry related to network issue or operation
Threat - Log entry related to a threat condition
### LOG_TYPE Values for Log Management
ShowModuleMethodAndLineNumber – Tells JLogger to include any available values
for what module name, method name, and line number the exception or log entry
was made. This is very useful for finding and correcting bugs in development,
quality assurance, and production code.
ShowTimeOnly - Shows time only, not date, in the debug log. Useful since debug
logs are closed and a new one created on the first write the next day after the
log file was opened. Do not use this flag if you want each log entry to show
date and time.
HideThreadID - Hides the thread ID from being printed in the debug log.
IncludeStackTrace – Writes the stack trace to the debug log. Otherwise, leaves
that column blank.
SendEmail – This is used if sending an email from a log entry that also uses
SendMail. The flag, when used in management (DebugLogOptions) enables sending
email if the log entry also calls for it by use of this flag. If this flag is
not set, the use of SendMail in a specific log entry is ignored, and no email is
sent. This allows globally turning email sends on and off by simply changing the
DebugLogOptions of the Logger instance.
IncludeExceptionData – This tells the JLogger instance to examine the Data
collection on all Exceptions, and log any name-value pairs it finds there. The
Exception.Data collection is often used in catch blocks to add real time values
to the exception before executing a “throw”. Use of the Data collection for this
saves much time in troubleshooting.
Example Code
------------
These lines of code are used to illustrate the use of JLogger. There are more
variations than documentation can show, but this shows a fully functioning use
of JLogger.
using Jeff.Jones.JLogger;
using Jeff.Jones.JHelpers;
LOG_TYPE m_DebugLogOptions = LOG_TYPE.Error | LOG_TYPE.Informational |
LOG_TYPE.ShowTimeOnly |
LOG_TYPE.Warning |
LOG_TYPE.HideThreadID |
LOG_TYPE.ShowModuleMethodAndLineNumber |
LOG_TYPE.System |
LOG_TYPE.SendEmail;
Boolean response = false;
String filePath = CommonHelpers.CurDir + @"\";
String fileNamePrefix = "MyLog";
Int32 daysToRetainLogs = 30;
response = Logger.Instance.SetLogData(filePath, fileNamePrefix, daysToRetainLogs, logOptions, "");
Int32 smtpPort = 587;
Boolean useSSL = true;
List<String> sendToAddresses = new List<String>();
sendToAddresses.Add("MyBuddy@somewhere.net");
sendToAddresses.Add("John.Smith@anywhere.net");
response = Logger.Instance.SetEmailData("smtp.mymailserver.net", "logonEmailAddress@work.net",
"logonEmailPassword", smtpPort, sendToAddresses,
"emailFromAddress@work.net", emailReplyToAddress@work.net>",
useSSL);
// End of email setup.
// This starts the log operation AFTER you have set the initial parameters.
response = Logger.Instance.StartLog();
// This ends the configuration example
// Example of use in a method
void SomeMethod()
{
// Use of the Flow LOG_TYPE shows in the log when a method was entered,
// and exited. Useful for debugging, QA, and development. The Flow bit
// mask is usually turned off in production to reduce log size.
if ((m_DebugLogOptions & LOG_TYPE.Flow) == LOG_EXCEPTION_TYPE.Flow)
{
Logger.Instance.WriteToDebugLog(LOG_TYPE.Flow, "1st line in method","");
}
// This variable notes when the method started.
DateTime methodStart = DateTime.Now;
try
{
// Do some work here
// This is an example of logging used during
// process flow. The bitmask used here does not
// have to be "Informational", and may be turned
// off in production.
if ((m_DebugLogOptions & LOG_TYPE.Informational) == LOG_TYPE.Informational)
{
Logger.Instance.WriteToDebugLog(LOG_TYPE.Informational,
"Primary message", "Optional detail message");
}
// Do some more work
}
catch (Exception exUnhandled)
{
// Capture some runtime data that may be useful in debugging.
exUnhandled.Data.Add("SomeName", "SomeValue");
if ((m_DebugLogOptions & LOG_TYPE.Error) == LOG_TYPE.Error)
{
Logger.Instance.WriteToDebugLog(LOG_TYPE.Error, exUnhandled, "Optional detail message");
}
}
finally
{
if ((m_DebugLogOptions & LOG_TYPE.Performance) == LOG_TYPE.Performance)
{
TimeSpan elapsedTime = DateTime.Now - methodStart;
Logger.Instance.WriteToDebugLog(LOG_TYPE.Performance,
String.Format("END; elapsed time = [{0:mm} mins, {0:ss} secs, {0:fff} msecs].",
objElapsedTime));
}
// Capture the flow for exiting the method.
if ((m_DebugLogOptions & LOG_TYPE.Flow) == LOG_EXCEPTION_TYPE.Flow)
{
Logger.Instance.WriteToDebugLog(LOG_TYPE.Flow, "Exiting method", "");
}
} // END of method
Logger Methods and Properties
-----------------------------
### Static
DEFAULT_DEBUG_LOG_OPTIONS – constant with manufacturer recommend initial
settings. You do NOT have to use this and can build your own that resides in
your program.
DEFAULT_LOG_RETENTION – constant that is the default for how many days log files
are retained. You can use your own value and do NOT have to use this one.
LOG_CACHE_FREQUENCY – constant for how long between attempts to write the log
queue to the log file, in milliseconds.
### Instance
DaysToRetainLogs – (Get/Set) - How many days that the Logger instance retains
previous log files.
DebugLogOptions – (Get/Set) - The debug flags that are active during the
lifetime of the Logger instance
Dispose() – Implement the IDisposable.Dispose() method. Developers are supposed
to call this method when done with this Object. There is no guarantee when or if
the GC will call it, so the developer is responsible to. GC does NOT clean up
unmanaged resources, such as COM objects, so we have to clean those up, too.
There are no COM objects used in JLogger.
EmailEnabled – (Get ONLY) - True if sending email is enabled globally, false if
off globally. Email sending is set by the LOG_TYPE.SendMail bit being on or off
in DebugLogOptions,
EmailLogonName - (Get/Set) - The logon name expected by the SMTP email server.
EmailPassword - (Get/Set) - The logon password expected by the SMTP email
server.
EmailServer - (Get/Set) - The IP address or DNS name of the outgoing mail server
FromAddress - (Get/Set) - The email address to use with sending emails to
indicate who the email is from.
IsDisposing – (Get ONLY) - Tells the caller if this instance is already being
disposed. Returns true if the JLogger instance is being disposed, false if not.
LogFileName – (Get ONLY) - Fully qualified file name for the log file.
LogPath - (Get/Set) - Fully qualified path for the log file.
ReplyToAddress - (Get/Set) - The email address used to tell the recipient what
address to reply to.
SendToAddresses – (Get ONLY List<string>, but List<string> still supports
Add and other functionality. List<string> cannot be “set” as a List\<string\> object – internal creation only.) - These are the email addresses for log emails to be sent to.
Boolean SetEmailData(String emailServer,
String emailLogonName,
String emailPassword,
Int32 smtpPort,
List<String> sendToAddresses,
String fromAddress,
String replyToAddress,
Boolean useSSL) – Configure the email send functionality.
Boolean SetLogData(String logPath,
String logFileNamePrefix,
Int32 daysToRetainLogs,
LOG_TYPE debugLogOptions,
String emergencyLogPrefixName = DEFAULT_EMERG_LOG_PREFIX) –
Configures the Logger for logging before starting the log.
SMTPPort – (Get/Set) - The port that the SMTP email server listens on.
Boolean StartLog() – Once the Logger instance is configured, this is used to
start logging.
Boolean StopLog() – When the Logger instance is running, this is used to stop
logging.
UseSSL – (Get/Set) - True if the email server requires using SSL, false if not.
Boolean WriteDebugLog(LOG_TYPE pExceptionType,
Exception pExceptionToUse,
String pOptionalLogMessage) - Method used to write exception information to the log. This method writes a DebugLogItem instance to a queue, which is then emptied FIFO on a separate thread so calling this method does not block main thread activity.
Boolean WriteDebugLog(LOG_TYPE pExceptionType,
String message,
String secondaryMessage = "") - Method used to write message information to the log. This method writes a DebugLogItem instance to a queue, which is then emptied FIFO on a separate thread so calling this method does not block main thread activity.
|
|
|
|
|
JDAC Data Access Component
==========================
JDAC is a .NET Standard 2.0 library component that can be used with any .NET
project, whether Core or Standard, on any supported OS to access SQL Server. The
library provides versatile and easy access to execute SQL queries or execute SQL
with no returned dataset. There are also some built-in queries for schema
information, and methods to convert System.Datat.DataTable objects to various
uses. Details are provided below, along with code samples.
Understanding the DBReturnValue object
--------------------------------------
When executing a query of any kind, there is an opportunity to do more than just
execute a query. There may be return parameters or a return code. If something
goes wrong and an exception is thrown, it is often the case that there are
multiple layers of exceptions that could be examined to troubleshoot the issue.
DBReturnValue has several properties that address these issues and any
System.Data.Dataset that is returned. The class is marked “[Serializable]”.
### Constructors
DBReturnValue() – the default constructor for the class.
DBReturnValue(List<SqlParameter> sqlParams, Int32 retCode, String errorMessage)
Constructor for providing the SQL Parameters, the return code, and an error
message, if any. This constructor is normally used internally.
### Properties
List<SqlParameter> - (Get/Set) the parameters passed in, and after execution,
the parameters are updated for any out parameters.
Int32 RetCode – (Get/Set) the return code from a query execution. It can be the
number of records affected, or a value representing status, depending on the
type of SQL executed. If it is “execute no query” SQL, then RetCode is the
number of records affected.
String ErrorMessage – (Get/Set) an error message coming back from the SQL
execution. If no exceptions, then it is an empty string.
System.Data.DataSet Data – (Get/Set) for calls that return data, this is the
dataset returned.
### Methods
Dispose() – Called, usually in a Finally block, to dispose of any resources the
object instance has. An internal flag ensures the internal Dispose process is
called only once. There is also a finalizer method for the Garbage Collector to
call.
Understanding the JDataAccessSQL Object
---------------------------------------
The JDataAccessSQL object is the workhorse for accessing data from SQL Server.
### Constructors
JDataAccessSQL() – Default constructor.
JDataAccessSQL(String server, String defaultDB, Boolean useAuthentication, String username,
String password, Int32 connectionTimeout, Int32 commandTimeout,
Int32 connectRetryCount = 3, Int32 connectRetryInterval = 10,
String applicationName = "", String workstationID = "",
Int32 portNumber = 1433, Boolean connectionPooling = true)
This constructor takes all the necessary and optional data points needed for a
connection to SQL Server. The last six parameters provide default values, in
case those are acceptable to you. When useAuthentication = true, use blank
strings for the username and password. If you use other values, they will be
ignored. For particulars on the parameters, see their matching Properties below.
### Properties
String Server - (Get/Set) Name of the server, including the instance name, if
used.
String DefaultDB - (Get/Set) The database to use as default in the connection
string.
Boolean UseAuthentication - (Get/Set) Whether to use Windows authentication or
not. True to use it, false to use a username and password.
String UserName - (Get/Set) Username to use if NOT using Windows Authentication
String Password - (Get/Set) Password to use if NOT using Windows authentication.
Int32 ConnectionTimeout - (Get/Set) Number of seconds for the connection object
to wait on a timeout exception.
Int32 CommandTimeout - (Get/Set) Number of seconds for a command object to wait
on an inactive command execution before timing out.
Int32 PortNumber - (Get/Set) Port number to use for connecting to SQL Server. If
0 or less, port 1433 is used. Default value is 1433.
Int32 ConnectRetryCount - (Get/Set) How many times to try reconnecting the
connection before throwing an exception. Default is 3. See also ConnectRetryInterval.
Int32 ConnectRetryInterval - (Get/Set) How long, in seconds, to wait between
reconnect attempts. Default is 10. See also ConnectRetryCount.
String ApplicationName - (Get/Set) Optional name for the application using this.
That value is used by SQL Server. Default value is an empty string.
String WorkstationID - (Get/Set) An ID string identifying the workstation the
connection is made from. This is optional. The default value is an empty string.
Boolean UseConnectionPooling – (Get/Set) True to use connection pooling
(default), and false if not.
String ConnectionString – (Get) Read-only connection string.
### Methods
async Task<Boolean> CheckConnectionAsync() - A true/false check to see if the
connection can be made.
Code example:
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20, 3, 10, "MyProgram", "MyComputer", 20161,
true);
Boolean retVal = dac.CheckConnectionAsync().Result;
dac.Dispose();
dac = null;
async Task<DBReturnValue> ExecuteQueryAsync(
String cmd,
Boolean isSP,
List<SqlParameter> sqlParams)
Asynchronous method to execute a query and return data. DBReturnValue instance
with results and parameters that have post-execution values.
Code Example:
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
String cmd = "SELECT * FROM dbo.Cookies WHERE ID > @id";
List<SqlParameter> queryParams = new List<SqlParameter>();
queryParams.Add(new SqlParameter
{
DbType = DbType.Int64,
ParameterName = "@id",
Value = 0
});
DBReturnValue dbRetVal = dac.ExecuteQueryAsync(cmd, false, queryParams).Result;
DataSet retVal = dbRetVal.Data;
dac.Dispose();
dac = null;
async Task<DBReturnValue> ExecuteStatementAsync(
String cmd,
Boolean isSP,
List<SqlParameter> sqlParams)
Asynchronous method to execute SQL that does not return a dataset. DBReturnValue
instance with results and parameters that have post-execution values.
Code Example:
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
String cmd = "UPDATE dbo.Cookies SET Name='Raspberry' WHERE ID = \@id";
List<SqlParameter> queryParams = new List<SqlParameter>();
queryParams.Add(new SqlParameter
{
DbType = DbType.Int64,
ParameterName = "@id",
Value = 1
});
DBReturnValue dbRetVal = dac.ExecuteStatementAsync(cmd, false, queryParams).Result;
dac.Dispose();
dac = null;
async Task<SQLServerData> GetServerPropertiesAsync() - Asynchronous method to
query data on the SQL Server properties. SQLServerData is serializable and has a data contract. The properties for the SQLServerData class are:
- String SvrName
- String ServerMachineName
- String EditionName
- String ProductVersion
- String ProductLevel
- String LicenseType
- Boolean IsIntegratedSecurityOnly
- Boolean IsClustered
- String Language
- String Platform
- String Description
- Int32 ProcessorsCount
Code Example
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
SQLServerData retVal = dac.GetServerPropertiesAsync().Result;
dac.Dispose();
dac = null;
async Task<List<String>> GetDatabaseNamesAsync() - Asynchronous method to
get a list of database names. More complete data can be obtained by using the GetSchema(SchemaTypesEnum.Databases) method. A list of string names for the databases is returned by this method.
Code Example
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
List<String> retVal = dac.GetDatabaseNamesAsync().Result;
dac.Dispose();
dac = null;
async Task<DataTable> GetDatabaseRelationshipsAsync(String targetDatabase = "") - Asynchronous method to get a list or relationships in the database
specified. Default database is the one specified in the connection string.
Returns a System.Data.DataTable with relationship data. The columns are all
String with the following names:
- Foriegn_Key_Name
- Parent_Table
- Primary_Key_Column
- Child_Table
- Foriegn_Key_Column
Code Example
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
DataTable retVal = dac.GetDatabaseRelationshipsAsync("Test").Result;
dac.Dispose();
dac = null;
async Task<List<String>> GetTableNamesAsync(String targetDatabase = "") -
Asynchronous method to get names of tables for the database specified, or by
default uses the database named in the connection string. The method returns a
list of table names for the database specified, or by default the database named
in the connection string.
Code Example
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
List<String> retVal = dac.GetTableNamesAsync().Result;
dac.Dispose();
dac = null;
async Task<DataTable> GetSchemaAsync(SchemaTypesEnum schemaType, String targetDatabase = "") - Asynchronous method to get the schema elements data based on the schema type requested. The method returns a DataTable with the schema definitions. DataTable columns vary with each schema type. You can use the SchemaFactory object to get the same schema information as serializable objects
with properties specific to the schema type.
SchemaTypesEnum
- Unspecified - Default value
- MetaDataCollections - Lists the names of the known schemas
- DataSourceInformation = SQL Server information
- DataTypes = List of SQL Server data types and info, plus their .NET equivalents
- ReservedWords - List of reserved words in T-SQL for this server.
- Users - List of database users
- Databases - List of databases on the server
- Tables - List of tables for the database specified in the connection string.
- Columns - List of all columns in the tables for the database specified in the connection string.
- AllColumns - Functionally the same as Columns above, but may provide other columns not normally available.
- ColumnSetColumns - ColumnSets (SQL 2016 and newer)
- StructuredTypeMembers - List of structured types
- Views - List of views for the database specified in the connection string.
- ViewColumns - List of columns in views for the database specified in the connection string.
- ProcedureParameters - List of parameters for stored procedures for the database specified in the connection string.
- Procedures - List of stored procedures for the database specified in the connection string.
- ForiegnKeys - Data on foriegn key relationships for the database specified in the connection string.
- IndexColumns - List of indices and their columns for the database specified in the connection string.
- Indexes - List of indexes for the database specified in the connection string.
- UserDefinedTypes - List of user-defined types for the database specified in the connection string.
Code Example
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
DataTable retVal = dac.GetSchemaAsync(SchemaTypesEnum.AllColumns).Result;
dac.Dispose();
dac = null;
Understanding the SchemaFactory Object
--------------------------------------
The SchemaFactory object is used to create and populate strongly typed objects that contain schema data. There are also some other methods that can be quite useful.
### Methods
async Task<String> ConvertTableToCSClassAsync(DataTable dt, String namespaceName, String className)
Takes a DataTable and creates a data object C# class as a string. The class is marked for serialization and use as a data object. You specify the namespace you want the class to have, and the name of the .cs class. The method returns a String that can be written to a file as a C# class. One example of the use for this function is when using this library to execute SQL, you can take the
DataTable that is returned from a SQL query, use it in this method, and now you have a C# class, fully coded and ready to compile. This method was used to create the code for the schema classes used in this library.
Code Example:
SchemaFactory fac = new SchemaFactory();
String csClass = fac.ConvertTableToCSClassAsync(retVal, "MyNamespace.Something",
schemaType.ToString() + "DO").Result;
System.IO.File.WriteAllText(Environment.CurrentDirectory + @"\" + schemaType.ToString() + "DO.cs",
csClass);
fac = null;
async Task<String> GetFactoryMethodSchemaCodeAsync(DataTable dt, SchemaTypesEnum schemaType,
String altDOName = "Test")
Creates the code for an async method to populate a DO class, using a JDataAccessSQL data access component passed in as a parameter. The method is specific to a DO created by ConvertTableToCSClass(), using the schemaType and DataTable passed in. The method returns a string with the full C# method code. One example of the usage of this method is to create the code needed to create the corresponding class for the schema. This method was used for code generation
for some of this library.
Code Example
SchemaFactory fac = new SchemaFactory();
DataTable retVal = <some DataTable>
SchemaTypesEnum schemaType = <one of the SchemaTypesEnum enum values other than Undefined>
String factoryMethod = fac.GetFactoryMethodSchemaCodeAsync(retVal, schemaType).Result;
System.IO.File.AppendAllText(Environment.CurrentDirectory + @"\SchemaFactoryMethod.cs",
factoryMethod);
fac = null;
async Task<String> GetFactoryMethodCodeAsync(DataTable dt, String dOName)
This method takes a DataTable object, and creates the C# code for a method to populate an instance of a class (the class name is represented by the String parameter dOName). The properties MUST have the same name and case-sensitive spelling as the column names in the DataTable. If you used the method
"ConvertTableToCSClassAsync" in this SchemaFactory object, that part will be taken care of. Note that the class represented by the name dOName is one data row, not a collection.
Code Example:
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
DBReturnValue retVal = dac.ExecuteQueryAsync("SELECT * FROM Cookies", false, null).Result;
DataTable retTable = retVal.Data.Tables[0];
SchemaFactory sf = new SchemaFactory();
String tempCSFile = sf.ConvertTableToCSClassAsync(retTable,
"YourNamespace.Cookies", "CookieDO").Result;
String tempMethod = sf.GetFactoryMethodCodeAsync(retTable, "CookieDO").Result;
sf = null;
dac.Dispose();
dac = null;
So now you can have this library write the C# class file and the method to
populate it, all from an instance of the DataTable from your query.
async Task<String> GetDataTableContentsAsDelimitedFileAsync(DataTable dataTable,
String fieldDelimiter)
Takes a DataTable and creates a string to use for a delimited file from the data, using the specified field delimiter. The caller must decide what to use as a delimiter that would not be used in the data. The value [((Char)28).ToString()] is recommended.
Code Example
SchemaFactory fac = new SchemaFactory();
DataTable retVal = <some DataTable>
String schema = fac.GetDataTableContentsAsDelimitedFileAsync(retVal, ((Char)28).ToString()).Result;
fac = null;
async Task<String> GetDataTableSchemaAsDelimitedFileAsync(DataTable dataTable,
String fieldDelimiter)
Takes a DataTable and creates a delimited file from the schema, using the specified field delimiter. The caller must decide what to use as a delimiter that would not be used in the data. The value [((Char)28).ToString()] is recommended. The method returns a String containing the delimited file.
Code Example:
SchemaFactory fac = new SchemaFactory();
DataTable retVal = <some DataTable>
String schema = fac.GetDataTableSchemaAsDelimitedFileAsync(retVal, ((Char)28).ToString()).Result;
fac = null;
The following methods return schema objects with information on specific schema
collections that correspond to the SchemaTypesEnum enumeration. This method
creates and populates an object instance with the data about the schema type
query matching the returned object.
This is a typical code example. You may adapt it to any of the methods.
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
"CookieStore", true, "", "", 10, 20,
3, 10, "MyProgram", "MyComputer", 20161, true);
SchemaFactory fac = new SchemaFactory();
DataTable retVal = <some DataTable>
List<AllColumnsDO> returnValue = fac.GetAllColumnsDO(dac).Result;
fac = null;
async Task<List<AllColumnsDO>> GetAllColumnsDO(JDataAccessSQL dac)
async Task<List<ColumnsDO>> GetColumnsDO(JDataAccessSQL dac)
async Task<List<ColumnSetColumnsDO>> GetColumnSetColumnsDO(JDataAccessSQL dac)
async Task<List<DatabasesDO>> GetDatabasesDO(JDataAccessSQL dac)
async Task<List<DataSourceInformationDO>> GetDataSourceInformationDO(JDataAccessSQL dac)
async Task<List<DataTypesDO>> GetDataTypesDO(JDataAccessSQL dac)
async Task<List<ForiegnKeysDO>> GetForiegnKeysDO(JDataAccessSQL dac)
async Task<List<IndexColumnsDO>> GetIndexColumnsDO(JDataAccessSQL dac)
async Task<List<IndexesDO>> GetIndexesDO(JDataAccessSQL dac)
async Task<List<MetaDataCollectionsDO>> GetMetaDataCollectionsDO(JDataAccessSQL dac)
async Task<List<ProcedureParametersDO>> GetProcedureParametersDO(JDataAccessSQL dac)
async Task<List<ProceduresDO>> GetProceduresDO(JDataAccessSQL dac)
async Task<List<ReservedWordsDO>> GetReservedWordsDO(JDataAccessSQL dac)
async Task<List<StructuredTypeMembersDO>> GetStructuredTypeMembersDO(JDataAccessSQL dac)
async Task<List<TablesDO>> GetTablesDO(JDataAccessSQL dac)
async Task<List<UserDefinedTypesDO>> GetUserDefinedTypesDO(JDataAccessSQL dac)
async Task<List<UsersDO>> GetUsersDO(JDataAccessSQL dac)
async Task<List<ViewColumnsDO>> GetViewColumnsDO(JDataAccessSQL dac)
async Task<List<ViewsDO>> GetViewsDO(JDataAccessSQL dac)
|
|
|
|
|
|
Another really good source for imaging for app development is iconarchive.com, mostly free high quality icons and pictograms.
forging iron and new ideas
|
|
|
|
|
A few weeks ago, a guy posted an article about a backup utility he had written. The way it works is that you give it a source directory and one-or-more target directories. It then backs up the source to the oldest target directory. In this way, you can keep a recent history of a directory for, say, the last week by running it daily on seven target directories.
This happens to be precisely what I want, and I thought to myself, 'I must keep that post and install this when I get chance.' Unfortunately, I seem to have done my usual trick of putting it somewhere so safe that even I can't find it.
Does any of this ring a bell with anyone out there? If not, can anyone suggest an alternative (preferably free, 'cos money is tight) tool that can do something similar?
Any help would be very gratefully received.
Kind wishes - Patrick
Thank you to anyone taking the time to read my posts.
|
|
|
|
|