BPSoftware.com
Home   Utilities   Purchase   FAQ   Support   Contact        
Shareware Utilities
 APrintDirect
 AIconExtract
 AFile Attribute Manager
Freeware Utilities
 AddrMon
 AFileSync
 ASysIcon
 B&P Table Utilities
 BPACLer
 BPSNMPMon
 BPSNMPUtil
 CharCount
 Delphi® Components
 MacAddr
Miscellaneous
 BPSoftware Blog
 Purchase Shareware
 Support

 


Saturday, May 27, 2006
Custom Word Fields

The use of Field information in Microsoft® Word allows for easier maintenance of your documents. Using fields, you can include references to document property information within your document. This avoids the need to update changing property information that is referenced within a document (title, author, etc...). Using fields with templates makes format standardization a bit more exciting. Besides the standard fields, you can also reference your custom document properties. Personally, I often reference custom document revision information.


To reference custom properties in your document you first need to set them up. In my case, I use MAJ_REV and MIN_REV, both of these are of type Number. In your Word document move the cursor to the location where you would like to insert your custom property and press CTRL+F9. This will insert a Word field denoted by brackets (note that you cannot type these in yourself, you must press CTRL+F9 to indicate it is a field). Between the brackets type DOCPROPERTY followed by the property name you would like to reference. While the cursor is still on the field, press F9 to update it and there you go….

Labels: , , ,

posted by Brad Prendergast at 8:09:00 AM (0 comments)
Links to this post
Permalink
Thursday, May 25, 2006
Adapter Information Round 2

In an earlier post getting local adapter information via the Internet Protocol Helper (IP Helper) was discussed. The .NET Framework version 2.0 has the System.Net.NetworkInformation namespace that provides access to this information. For this sample I used VB.NET, however I will try some 'blogged' tricks to see if I can get this working in BDS® 2006 and see how it all works out.




Imports System.Net.NetworkInformation
Imports System.Net

Public Sub RetrieveLocalAdapterInformation(ByVal text As TextBox)
Dim interfaces As NetworkInterface() 'NIC
Dim netInterface As NetworkInterface ' adapter
Dim properties As IPInterfaceProperties
Dim address As PhysicalAddress
Dim ip As IPAddress
Dim ipinfo As IPAddressInformation

text.Clear()

If NetworkInterface.GetIsNetworkAvailable Then
interfaces = NetworkInterface.GetAllNetworkInterfaces

If interfaces.GetLength(0) > 0 Then
For Each netInterface In interfaces
properties = netInterface.GetIPProperties


text.AppendText(netInterface.Name & vbCrLf)
text.AppendText("Id: " & netInterface.Id.ToString & vbCrLf)
address = netInterface.GetPhysicalAddress
text.AppendText("MAC Address: " & (Microsoft.VisualBasic.IIf(address.ToString = String.Empty, "None", address.ToString)) & vbCrLf)
For Each ipinfo In properties.UnicastAddresses
text.AppendText("IP: " & ipinfo.Address.ToString & vbCrLf)
Next
For Each ip In properties.DhcpServerAddresses
text.AppendText("DHCP Server: " & ip.ToString & vbCrLf)
Next
For Each ip In properties.DnsAddresses
text.AppendText("DNS Server: " & ip.ToString & vbCrLf)
Next
text.AppendText("Type: " & netInterface.NetworkInterfaceType.ToString & vbCrLf)
text.AppendText("Operational Status: " & netInterface.OperationalStatus.ToString & vbCrLf)
text.AppendText("Speed: " & netInterface.Speed.ToString("N") & " bytes" & vbCrLf)

' XP Only
'text.AppendText("Receive Only: " & netInterface.IsReceiveOnly.ToString & vbCrLf)

' XP Only
'text.AppendText("Support Multicast: " & netInterface.SupportsMulticast.ToString & vbCrLf)


text.AppendText("Support IPv4: " & netInterface.Supports(NetworkInterfaceComponent.IPv4).ToString & vbCrLf)
text.AppendText("Support IPv6: " & netInterface.Supports(NetworkInterfaceComponent.IPv6).ToString & vbCrLf)
text.AppendText("DnsSuffix: " & properties.DnsSuffix.ToString & vbCrLf)
text.AppendText("" & vbCrLf)
Next
End If
End If
End Sub

Labels: , ,

posted by Brad Prendergast at 8:51:00 PM (0 comments)
Links to this post
Permalink
Local Computer Adapter Information

Most computers today have some sort of adapter for connecting to a network. It is often desirable to retrieve the local computer’s adapter information. The .NET Framework version 2.0 has the System.Net.NetworkInformation namespace to provide easy access to this and a lot of other adapter information. In the WIN32 world there is the Internet Protocol Helper (IP Helper), specifically the GetAdaptersInfo function. If you are using BDS® 2006 (or earlier versions) grab the IP Helper API from the JEDI Project (there is a lot of work in that project and we should all thank the contributors of that project).

With the IP Helper wrapper, getting the local adapter information is as easy as:
uses
IpHlpApi, IpTypes;

procedure RetrieveLocalAdapterInformation(strings: TStrings);
var
pAdapterInfo: PIP_ADAPTER_INFO;
AdapterInfo: IP_ADAPTER_INFO;
BufLen: DWORD;
Status: DWORD;
strMAC: String;
i: Integer;
begin
strings.Clear;

BufLen:= sizeof(AdapterInfo);
pAdapterInfo:= @AdapterInfo;

Status:= GetAdaptersInfo(nil, BufLen);
pAdapterInfo:= AllocMem(BufLen);

try
Status:= GetAdaptersInfo(pAdapterInfo, BufLen);

if (Status <> ERROR_SUCCESS) then
begin
case Status of
ERROR_NOT_SUPPORTED:
strings.Add('GetAdaptersInfo is not supported by the operating ' +
'system running on the local computer.');
ERROR_NO_DATA:
strings.Add('No network adapter on the local computer.');
else
strings.Add('GetAdaptersInfo failed with error #' + IntToStr(Status));
end;
Exit;
end;

while (pAdapterInfo <> nil) do
begin
strings.Add('Description: ' + pAdapterInfo^.Description);
strings.Add('Name: ' + pAdapterInfo^.AdapterName);

strMAC := '';
for I := 0 to pAdapterInfo^.AddressLength - 1 do
strMAC := strMAC + '-' + IntToHex(pAdapterInfo^.Address[I], 2);
Delete(strMAC, 1, 1);
strings.Add('MAC address: ' + strMAC);
strings.Add('IP address: ' + pAdapterInfo^.IpAddressList.IpAddress.S);
strings.Add('Gateway: ' + pAdapterInfo^.GatewayList.IpAddress.S);
strings.Add('DHCP enabled: ' + IntTOStr(pAdapterInfo^.DhcpEnabled));
strings.Add('DHCP: ' + pAdapterInfo^.DhcpServer.IpAddress.S);
strings.Add('Have WINS: ' + BoolToStr(pAdapterInfo^.HaveWins,True));
strings.Add('Primary WINS: ' + pAdapterInfo^.PrimaryWinsServer.IpAddress.S);
strings.Add('Secondary WINS: ' + pAdapterInfo^.SecondaryWinsServer.IpAddress.S);

pTempAdapterInfo := pAdapterInfo;
pAdapterInfo:= pAdapterInfo^.Next;
Dispose(pTempAdapterInfo);
end;
finally

Dispose(pAdapterInfo);
end;
end;


Note: Responding to a newsgroup posting gave me the idea of posting this blog message.

Labels: , ,

posted by Brad Prendergast at 7:10:00 AM (0 comments)
Links to this post
Permalink
Sunday, May 21, 2006
Event Log (Part 2)

In a previous post, I had mentioned that I needed something with a little more ‘oomph’ than the ‘standard’ Windows® Event Viewer. After giving some thought to what type of application to write, I began to contemplate how I was going to access the EventLogs on various machines. For this task I decided to give the EventLog Class a shot. The EventLog Class is found in the System.Diagnostics namespace. During my ‘exploration’ via creating a basic application, I was pleasantly surprised at how easy and fast I was able to create a basic yet functional EventLog Viewer.

Using BDS® 2006 (and yes, I also created a version with VB.NET using Visual Studio® 2005 -- I wanted to work with some of the .NET 2.0 changes to the EventLog Class -- I’ll post that code later), I created a new Windows Form Application.
For this basic application I placed an ImageList, TreeView, ListView and RichTextBox (separated by splitters to allow for sizing) onto the form. The ‘basic application’ concept was to display the available Event Logs for a computer in the TreeView. When an event log is selected within the TreeView, the ListView displays the selected EventLlog's entries. When and entry is selected in the ListView, the ‘event’ message is displayed in the RichTextBox. I had placed some images in the ImageList to cosmetically spruce things up a bit.




Here is the gist of some simple code: (Minor property adjustments and event assignments are not listed, but should be obvious)
const
//Image constants- the image locations in the ImageList
COMPUTERIMG= 0;
LOGIMG= 2;
ERRORIMG= 3;
WARNINGIMG= 4;
INFOIMG= 5;
AUDITIMG= 6;

type
stringarray= array of string;


// In the TWinForm class of the new form
private
strSelEvtLogName: string;
strSelComputerName: string;
procedure AddComputer(mytreeview: TreeView; computername: string);
procedure AppendLogMessage(myrichtextbox: RichTextBox; logname: string;
computername: string; index: Integer);
procedure DisplayLogEntries(mylistview: ListView; logname: string;
computername: string);
function GetEventLogNames(computername: string):stringarray;

// The class code
procedure TWinForm.DisplayLogEntries(mylistview: ListView; logname,
computername: string);
var
e: EventLog;
entry: EventLogEntry;
listitem: ListViewItem;
oldCursor: System.Windows.Forms.Cursor;
begin
e:= EventLog.Create(logname, computername);
oldCursor:= Cursor;
Cursor:= Cursors.WaitCursor;

mylistview.BeginUpdate;
mylistview.Items.Clear;

for entry in e.Entries do
begin
// Set the image index for the entry type
Case entry.EntryType of
EventLogEntryType.Error: begin // 1
listitem:= mylistview.Items.Add('Error');
listitem.ImageIndex:= ERRORIMG;
end;
EventLogEntryType.FailureAudit: begin // 16
listitem:= mylistview.Items.Add('Failure Audit');
listitem.ImageIndex:= AUDITIMG;
end;
EventLogEntryType.Information: begin // 4
listitem:= mylistview.Items.Add('Information');
listitem.ImageIndex:= INFOIMG;
end;
EventLogEntryType.SuccessAudit: begin // 8
listitem:= mylistview.Items.Add('Success Audit');
listitem.ImageIndex:= AUDITIMG;
end;
EventLogEntryType.Warning: begin // 2
listitem:= mylistview.Items.Add('Warning');
listitem.ImageIndex:= WARNINGIMG;
end;
end;


listitem.SubItems.Add(entry.TimeGenerated.ToLocalTime.ToString);
listitem.SubItems.Add(entry.Source);
listitem.SubItems.Add(entry.Category);

// The EventID property has been deprecated. in 2.0
listitem.SubItems.Add(entry.EventID.ToString);

// Note: The InstanceId property is new in the .NET Framework version 2.0.
//listitem.SubItems.Add(entry.InstanceId);


listitem.SubItems.Add(entry.UserName);
listitem.SubItems.Add(entry.MachineName);

//Remarks: Index is not necessarily zero-based. I love stuff like this
listitem.SubItems.Add(entry.Index.ToString);
end;

mylistview.EndUpdate;
Cursor:= oldCursor;

end;

procedure TWinForm.AddComputer(mytreeview: TreeView; computername: string);
var
strNames: stringarray;
strMy: string;
computernode,lognode: TreeNode;
begin
// Get a list of the event logs for a computer
strNames:= GetEventLogNames(computername);

computerNode:= mytreeview.Nodes.Add(computername);
computerNode.ImageIndex:= COMPUTERIMG;
for strMy in strNames do
begin
logNode:= computerNode.Nodes.Add(strMy);
logNode.ImageIndex:= LOGIMG;
logNode.SelectedImageIndex:= logNode.ImageIndex;
end;
end;


procedure TWinForm.AppendLogMessage(myrichtextbox: RichTextBox; logname,
computername: string; index: Integer);
var
e: EventLog;
entry: EventLogEntry;
begin
e:= EventLog.Create(logname, computername);
entry:= e.Entries.Item[index];
myrichtextbox.AppendText(entry.Message);
end;

function TWinForm.GetEventLogNames(computername: string):stringarray;
var
c: Integer;
eventlogs: array of EventLog;
e: EventLog;
strNames: stringarray;
begin
c:= 0;
eventlogs:= EventLog.GetEventLogs(computername);

// Resize the array to number of eventlog names
SetLength(strNames, High(eventlogs)+1);

// Loop through the eventlogs and get the names
for e in eventLogs do
begin
strNames[c]:= e.LogDisplayName;
c:= c + 1;
end;

result:= strNames;
end;

procedure TWinForm.TreeView1_AfterSelect(sender: System.Object; e: System.Windows.Forms.TreeViewEventArgs);
var
myTreeView: TreeView;
myNode: TreeNode;
myParentNode: TreeNode;
begin
if
sender is TreeView then
begin

myTreeView:= sender as TreeView;
myNode:= myTreeView.SelectedNode;
if (myNode.Parent <> Nil) then
begin
myParentNode:= myTreeView.SelectedNode.Parent;
strSelEvtLogName:= myNode.Text;
strSelComputerName:= myParentNode.Text;
DisplayLogEntries(ListView1, strSelEvtLogName, strSelComputerName);
end
else
begin

ListView1.Items.Clear;
end;
end;
end;


procedure TWinForm.ListView1_SelectedIndexChanged(sender: System.Object; e: System.EventArgs);
var
myItem: ListViewItem;
mySubItem: ListViewItem.ListViewSubItem;
index: Integer;
begin
RichTextBox1.Clear;
for myItem in ListView1.SelectedItems do
begin
index:= myItem.Index;
//mySubItem:= myItem.SubItems.Item[7];
//index:= Convert.ToInt32(mySubItem.Text) - 1;

AppendLogMessage(RichTextBox1, strSelEvtLogName, strSelComputerName, index);
end;
end;

procedure TWinForm.TWinForm_Load(sender: System.Object; e: System.EventArgs);
begin
// Add information for the local computer
AddComputer(TreeView1, SystemInformation.ComputerName);
// Expand display
TreeView1.ExpandAll;
end;

The writing of an event to a log looks just as simple, although I haven't had the opportunity to play with that yet.

Labels: , ,

posted by Brad Prendergast at 6:02:00 PM (0 comments)
Links to this post
Permalink
LINQ CTP (May 2006)

Microsoft® has an informative Language-Integrated Query (LINQ) Community Technology Preview available for download here.

Labels: ,

posted by Brad Prendergast at 5:21:00 AM (0 comments)
Links to this post
Permalink
Thursday, May 18, 2006
Event Log (Part 1)

A few months back I made a couple of posts (Part 1, Part 2) regarding Microsoft’s LogParser. Since that time I have been getting my fair share of use from it. Recently, I had the need to analyze the Event Logs on a number of machines. There is the EventLog Snap-In for MMC; however this really doesn’t allow you to do more than basic viewing or broad filtering of events. (One thing I will give it is that it allows for the connection to the event logs on remote machines. Admittedly, I do have a saved console with about 5 or so machines that I browse through the logs of often.) Once again this Free Gem came to my rescue. One of the input sources of LogParser is the EventLog (EVT) Input Format. With LogParser you can select EventLog data (using a SQL like syntax) from a local or remote EventLog and output it to one of LogParser’s output format.

The EVT fields available for selection are EventLog, RecordNumber, TimeGenerated, TimeWritten, EventID, EventType, EventTypeName, EventCategory, EventCategoryName, SourceName, Strings, ComputerName, SID, Message and Data.

With these fields a number of data extractions can be put together rather quickly. Here are a couple of basic ones (The charts are the actual charts created by LogParser):

logparser -o:DATAGRID "SELECT EventTypeName, EventCategoryName, TimeGenerated, SourceName, ComputerName FROM Application"

logparser -O:CHART -chartType:Column3D -chartTitle:"Count of Events" -values:ON -legend:OFF "SELECT TOP 20 SourceName, COUNT(SourceName) AS Count_Events INTO Events.gif FROM Application GROUP BY SourceName ORDER BY SourceName"

logparser -o:DATAGRID "SELECT EventTypeName, EventCategoryName, TimeGenerated, SourceName, ComputerName FROM \\COMPUTERNAME\Security"

logparser -o:DATAGRID "SELECT EventType, EventTypeName, EventCategoryName, Count(EventTypeName) AS Entries FROM Security GROUP BY EventType,EventTypeName,EventCategoryName"

logparser -o:CHART -chartType:Pie3D -chartTitle:"Event Categories" -values:ON -legend:ON "SELECT EventCategoryName, Count(EventTypeName) AS Entries INTO EVENT.GIF FROM Security GROUP BY EventCategoryName"


I have found the LogParser help file quite useful. There are plenty of examples, of which one explains how to do percentages.

I have also created an app using the EventLog Class that allows me to work with logs. This was my maiden voyage with this class and hopefully I’ll post on my experience shortly. I also hope to tighten it up for a more ‘universal use’ and post it for download.

Labels: , ,

posted by Brad Prendergast at 7:55:00 PM (0 comments)
Links to this post
Permalink
Wednesday, May 17, 2006
It is the Concept that Counts

The other day I had probably one of the better conversations I’ve had in a long time. The topic of the conversation was software development. This is one topic I could talk about non-stop and it also tends to bring out the conversationalist in me. The dialog was a friendly exchange was with a software developer that works primarily with development environments different from the ones I use (The opportunity to broaden horizons and discuss another viewpoint is one that I will rarely pass up).

In an effort to keep this short, the gist of the conversation focused on the concept that learning/understanding a development language (syntax) is similar to learning/understanding spoken language. This is a concept that I feel strongly about and fortunately, the other participant of the conversation felt as strongly as I do, leading to a very pleasant, yet intense conversation. Although it is possible, one does not typically memorize spoken language, rather they understand it, live it and feel it to a point where it becomes completely natural. Having an understanding of the concept of nouns, verbs and adjectives and the underlying knowledge of expression (a natural understanding of why and what to express) allows for the fluid ad hoc building of sentences and dialog. The ability to broaden one’s vocabulary also becomes easier. Memorizing what to say would result in a painfully drab and yet often out of place conversation.

Everyone has a ‘native tongue’, however the understanding and feeling of the basic concept of how to express oneself in certain situations allows for the cross-over of expression in other languages. Again, understanding (almost naturally) the concept of what to say allows one to figure how to translate that into another language for communication and expression of the concept. After all, most languages are similarly related and tend to result in the communication of expression. This same concept can be easily applied to software development environments/languages. Having a baseline conceptual (logical) understanding of what one is looking to achieve and how it all works is the foundation of developing an application; achieving a desired result, that can be built upon. With the understanding of the overall concept of what needs to be done (logically), a developer can generally search out the concept and find away to express that in another development language, whether it is Delphi®, Visual Basic, C, ASP, T/SQL, P/L SQL or whatever. After all, a development language is just that, isn’t it?

Well, enough of my rambling (I hope this makes enough sense to get some point across) for today I am off to play with some .NET EventLog stuff.

Labels: ,

posted by Brad Prendergast at 6:38:00 AM (0 comments)
Links to this post
Permalink
Sunday, May 14, 2006
myCursor Template

Well, for a brief moment, it seems I can come out from underneath the rock mountain that was placed atop my head. The more I use them, the more I like the code templates that are part of BDS® 2006. They can be a great savings when it comes to those repetetive 'code blocks'. Not only is the 'code block' inserted, but you can also have some dynamic content in them as well with the help of good the good ole' SyncEdit.
Generally, when I code a processing procedure/function I prefer to change the cursor to signify that something is 'happening' to the user. I often use the following code:
var
myCursor: TCursor;
begin
myCursor:= Screen.Cursor;
Screen.Cursor:= crHourglass;
try


finally
Screen.Cursor:= myCursor;
end;
end;


This code is simple enough, however it becomes easier with a good old 'scr' template. As you can see creating templates is rather simple and a great time saver.

Labels: ,

posted by Brad Prendergast at 12:00:00 PM (3 comments)
Links to this post
Permalink
Recent Posts
 Command Line: Visual Source Safe
 SQL: Remove / Delete Orphan Users
 SQL Delete/Drop a User from each Database
 Is there an 'I' in phone?
 SQL Optimization: Am I missing any indexes? - Part...
 Meaningful Signature File Quotes
 My Shared RSS Items
 Edit those XML files
 A little System.Diagnostics
 Wi-Fi Detector Shirt


Labels



Archives
 October 2005
 November 2005
 December 2005
 January 2006
 February 2006
 March 2006
 April 2006
 May 2006
 June 2006
 July 2006
 August 2006
 September 2006
 December 2006
 January 2007
 February 2007
 March 2007
 September 2007
 October 2007
 November 2007
 July 2008
 November 2008
Powered by Blogger