How to determine VB app compile/created date - vb.net

My company uses a software that, in the footer of it's about section lists the year 2001-2002. Is this sufficient grounds to believe that the last major overhaul or update that this program received would have been in 2001-02?
If not, is there a way through decompiling the software, it's written in VB6?

I forgot the linker sticks a timestamp into the PE Header. Here is a short VB.NET applet to read the PE Header and convert the timestamp:
Private Function GetPEDate(filename As String) As DateTime
Dim dtUINT As UInt32
Using fs As Stream = New FileStream(filename,
FileMode.Open, FileAccess.Read),
rdr As New BinaryReader(fs)
' move to PE location (60; 70 for 64 bit but
' there is no such thing as a 64bit VB6 app)
fs.Position = &H3C
Dim peHDR As UInt32 = rdr.ReadUInt32() ' offset of start location
fs.Position = peHDR
Dim tmpUINT = rdr.ReadUInt32() ' PE sig
Dim tmpShrt = rdr.ReadUInt16 ' machine
tmpShrt = rdr.ReadUInt16 ' sections
dtUINT = rdr.ReadUInt32() ' linker timestamp
End Using
' SEE NOTE
Dim dtCompiled As New DateTime(1970, 1, 1, 0, 0, 0)
dtCompiled = dtCompiled.AddSeconds(dtUINT)
dtCompiled = dtCompiled.AddHours( _
TimeZone.CurrentTimeZone.GetUtcOffset(dtCompiled).Hours)
Return dtCompiled
End Function
To use it:
Dim dt = GetPEDate(FullFilePath)
Console.WriteLine("App was compiled approx: {0}", dt.ToString)
Output:
App was compiled approx: 4/6/2004 11:54:07 AM
I tested this with some actual old VB6 apps as well as some x86 VB.NET apps and the DateTime returned is spot on compared to that of CreatedDate and/or Modified Date reported by Explorer.
Initially the time was off by 3 hours. The MSDN docs clearly state:
This field holds the number of seconds since December 31st, 1969, at 4:00 P.M.
But it was off by exactly 3 hrs and my TZ is not 3 away from East Coast US, Seattle or GMT. A quick Google yielded this article by Jeff Atwood (which includes another PE reader). Changing the base date to 1/1/1970 00:00:00 and adding the UTC adjustment returns times matching Explorer.
Apparently MSDN is wrong or out of date as to the base date. 1/1/1970 also seems more likely since corresponds to POSIX/Unix timestamps.

From WinNT.h note second DWord, TIMEDATESTAMP
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
If you look here you'll find above explained and a program to do it for you as well.
https://msdn.microsoft.com/en-au/library/ms809762.aspx?f=255&MSPPError=-2147217396

Related

Write bytes to a PLC device

I'm working around a connection between a PLC device and my companies PC. The PLC is the known Siemens S7-200 and I'm using vb.NET. Probably I should use another language but vb.NET is the one I'm more comfortable with. To do so, I'm also using a PPI protocol through COM1 and LibNoDave library to establish the connection.
The program I'm testing has to have Input 0.0 On, so I attached a switch to make it happen. Also I made a vb console to read (and write) the state of the Inputs and Outputs (as the LED physical indicators on the device) and also the state of the Bit memories:
The console reader (LEITOR section - sorry) is working like I intended and all the Q's, I's and M's are correctly lighting up if it is the case.
The problem is, to run the PLC program, I also have to lit up Q 1.1.
The Ladder Network that describes this has the following logical map:
I know I have to use the code:
Public FDS As libnodave.daveOSserialType 'Serial type
Public DI As libnodave.daveInterface 'Interface
Public DC As libnodave.daveConnection 'Connection
Public lPPI As Integer = 0 'Local
Public pPPI As Integer = 2 'PLC
Public RES As Integer = 0 'Response
Public REP As Integer = 0 'Response
Public buf(100) As Byte
Sub Code()
FDS.rfd = libnodave.setPort("COM1", "9600", AscW("E"))
DI = New libnodave.daveInterface(FDS, "IF1", lPPI, libnodave.daveProtoPPI, libnodave.daveSpeed93k)
DI.setTimeout(1000000)
DC = New libnodave.daveConnection(DI, pPPI, 0, 0)
RES = DC.connectPLC
'Write on PLC:
RES = DC.writeBytes(...
End sub
The code is working fine with no errors and an establish connection (until the last RESponse).
Here's the problem:
I can lit up the Output 1.1 (on the device and on the console) by doing the following:
RES = DC.writeBytes(libnodave.daveDB, 1, 1500, 16, buf)
where
buf = BitConverter.GetBytes(libnodave.daveSwapIed_16(30))
by repeating these two steps five more times (another time with 30 again, two more times with 50 and, finally, another two times with 50).
I'm pretty sure I'm doing something wrong, but there's not a lot of these commands description available online for a guy like me (who's just got started).
Can anyone explain what's going on? And also, How can I lit Q 1.1 with just one step?

getgroup() is very slow

I am using the function getgroup() to read all of the groups of a user in the active directory.
I'm not sure if I'm doing something wrong but it is very very slow. Each time it arrives at this point, it takes several seconds. I'm also accessing the rest of Active directory using the integrated function of "Accountmanagement" and it executes instantly.
Here's the code:
For y As Integer = 0 To AccountCount - 1
Dim UserGroupArray As PrincipalSearchResult(Of Principal) = UserResult(y).GetGroups()
UserInfoGroup(y) = New String(UserGroupArray.Count - 1) {}
For i As Integer = 0 To UserGroupArray.Count - 1
UserInfoGroup(y)(i) = UserGroupArray(i).ToString()
Next
Next
Later on...:
AccountChecker_Listview.Groups.Add(New ListViewGroup(Items(y, 0), HorizontalAlignment.Left))
For i As Integer = 0 To UserInfoGroup(y).Count - 1
AccountChecker_Listview.Items.Add(UserInfoGroup(y)(i)).Group = AccountChecker_Listview.Groups(y)
Next
Item(,) contains my normal Active directory data that I display Item(y, 0) contain the username.
y is the number of user accounts in AD. I also have some other code for the other information in this loop but it's not the issue here.
Anyone know how to make this goes faster or if there is another solution?
I'd recommend trying to find out where the time is spent. One option is to use a profiler, either the one built into Visual Studio or a third-party profiler like Redgate's Ants Profiler or the Yourkit .Net Profiler.
Another is to trace the time taken using the System.Diagnostics.Stopwatch class and use the results to guide your optimization efforts. For example time the function that retrieves data from Active Directory and separately time the function that populates the view to narrow down where the bottleneck is.
If the bottleneck is in the Active Directory lookup you may want to consider running the operation asynchronously so that the window is not blocked and populates as new data is retrieved. If it's in the listview you may want to consider for example inserting the data in a batch operation.

DateTime.ToLocalTime() stopped working on XP in August 2013

We have a VB.NET application installed on a customer's PC running XP, on which it appears that DateTime.ToLocalTime() has stopped working.
The problem first manifested itself in August 2013.
The customer is based in Texas, and their timezone is correct.
The documentation for DateTime.ToLocalTime() has the following interesting note:
On Windows XP systems, the ToLocalTime method recognizes only the current adjustment rule when converting from UTC to local time. As a result, conversions for periods before the current adjustment rule came into effect may not accurately reflect the difference between UTC and local time.
Therfore it appears likely that a timezone rule change was introduced in the August Windows Update, which has caused this.
I've found the following: http://support.microsoft.com/kb/2863058 which indicates that a cumulative timezone update was applied in August 2013, but no USA rules seem to be implicated in this change.
Has anyone else had experience of this problem, and (of course) a solution?
Edit
To clarify a bit. The times in question are stored in UTC in a SQL database, and we're converting to LocalTime for display. It's the display which is causing the problem.
Events which were recorded at 1500 localtime are now showing as recorded at 2100.
Will you be able to recode the product for the client?
You can use the Format function or the DateTime.Now, which gives you the date and time details of the local computer
Here give it a try:
Textbox1.text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt")
Textbox1.Text = Format(now, "yyyy-MM-dd hh:mm:ss")
you can change the date time details inside the string, just remember y=year, M=month, d=day, h=hour, m=minute, s=seconds.
If you have a back end database though, I'd recommend getting the time from it. (which would depend on the database)
This is just a guess, since you didn't show any code. (Please show code in your questions, it makes it much easier to help!)
Texas is currently in Central Standard Time, which is UTC-6. Since there are 6 hours difference between the times you reported (1500, 2100), my guess is that you are converting twice somehow.
This shouldn't happen under normal conditions, thanks to the .Kind property attached to the DateTime. For example:
DateTime dt1 = new DateTime(2013, 11, 22, 3, 0, 0, DateTimeKind.Utc);
Debug.WriteLine("{0:HH:mm} ({1})", dt1, dt1.Kind); // 3:00 (Utc)
DateTime dt2 = dt1.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt2, dt2.Kind); // 21:00 (Local)
DateTime dt3 = dt2.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt3, dt3.Kind); // 21:00 (Local)
But if somehow you loose track of the kind and it is set back to "unspecified", then the double conversion can happen:
DateTime dt1 = new DateTime(2013, 11, 22, 3, 0, 0, DateTimeKind.Utc);
Debug.WriteLine("{0:HH:mm} ({1})", dt1, dt1.Kind); // 3:00 (Utc)
DateTime dt2 = dt1.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt2, dt2.Kind); // 21:00 (Local)
// somehow, the kind is getting set back to unspecified in your code
dt2 = DateTime.SpecifyKind(dt2, DateTimeKind.Unspecified);
DateTime dt3 = dt2.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt3, dt3.Kind); // 15:00 (Local)
Now, it's unlikely that you are actually calling DateTime.SpecifyKind. Instead, I'd be looking in your code for some place where you store the local time back to the DB instead of the UTC time.
Or it could be that you convert the local DateTime to a string and read it back to another DateTime by parsing that string. That can happen in UI code. Perhaps you need to specify Local kind when gathering from a user on a form?
You should debug your code and step through so you can see how it is being transformed. I think then you will find the answer.
No, nothing happened in the Aug 2013 Windows Time Zone update that would affect the United States. The last DST change in the US was in 2007. Even then, you would be off by 1 hour, not 6.

.NET strange behaviour with datetimes and UTC to local time conversion

I'm modifying and old app and I found a big bug. I'm in Spain and this app is reading some files here which contain a date in a UTC string format, and is needed to be converted.
The string value is already converted to local time with CDate due to the format:
"yyyy-MM-yyTHH:mmZ"
But the code here converts again the date to a local value with .ToLocalTime, presumably making the time change again to a incorrect value.
The strange fact occurs now, where the var is taking the correct value, but the code is not returning that. In the "Inspection" secion in the Visual Studio you can see that the result should be 0, not 22 (hour 0 of next day).
What is happening here?
EDIT:
The app is reading a XML file, and in this point is reading this:
<IntervaloTiempo v="2013-10-26T19:33Z/2013-10-26T22:00Z"/>
The code is the one shown in the screenshot:
Valor = Split(.Value, "/")
dtUTC = CDate(Valor(0))
iHoraIn = Hour(dtUTC.ToLocalTime().AddHours(1))
I corrected the code with this, and the app is working the same way:
iHoraIn = dtUTC.AddHours(1).Hour
EDIT2:
Since it looks that my post is difficult to understand as seen in comments, I'll try clarify on some things.
I'm using Visual Studio 2005 with .NET Framework 2.0.
The value in dtUTC is converted to local time and its value, as you can see in the screenshot, is 21:33, which should return 22 with AddHour(1).Hour.
When using dtUTC.ToLocalTime() its hour should be converted to 23:33 value, which should return 0 with AddHour(1).Hour.
As you can see in the "Inspection" window, that is the behaviour. The problem is, the final value of the var iHoraIn is 22, which is correct, but the code is not.
Actually, changing the code to just deleting the ToLocalTime() part makes the final value the same.
Can someone explain why and how this is happening? Is this a bug?
DateTime.Kind
In Version 2.0 of the .Net framework, Microsoft introduced the DateTime.Kind property. The different kinds are as follows:
Local
Unspecified
Utc
Every Date (the underlying CLR type is DateTime) object has the Kind property, which specifies what kind of date that object is. That is, it specifies whether the date value is local, UTC, or unknown.
If a Date object has Kind = Local, then no conversion is performed when the ToLocalTime function is called. From the DateTime.ToLocalTime method, emphasis is mine:
Kind Results (of ToLocalTime)
----------- -----------------------------------------
Utc This instance of DateTime is converted to local time.
Local No conversion is performed.
Unspecified This instance of DateTime is assumed to be a UTC time,
and the conversion is performed as if Kind were UTC.
How does this apply to your situation?
When you use CDate, the resulting Kind is Local. This means that when you call ToLocal on it, no conversion takes place:
Dim valor = "2013-10-26T19:33Z"
Dim dtUTC = CDate(valor)
' dtUTC.Kind is Local
' The following does not do any conversion
Dim dtLocal = dtUTC.ToLocal()
A more complete example
This example shows what happens when you use CDate, and what happens when the Kind is explicitly set. The first two code blocks are equivalent - CDate creates a Local date. The third block shows what happens when you specify a UTC date.
Sub Main()
Dim valor = "2013-10-26T19:33Z"
Dim dtUTC = CDate(valor)
Dim dtLocal = dtUTC.ToLocalTime()
Dim iHoraIn = Hour(dtLocal.AddHours(1))
Dim kind = dtUTC.Kind
printDate(dtUTC, dtLocal, iHoraIn, kind)
Dim dtUTC2 = DateTime.SpecifyKind(dtUTC, DateTimeKind.Local)
Dim dtLocal2 = dtUTC2.ToLocalTime()
Dim iHoraIn2 = Hour(dtLocal2.AddHours(1))
Dim kind2 = dtUTC2.Kind
printDate(dtUTC2, dtLocal2, iHoraIn2, kind2)
Dim dtUTC3 = DateTime.SpecifyKind(dtUTC, DateTimeKind.Utc)
Dim dtLocal3 = dtUTC3.ToLocalTime()
Dim iHoraIn3 = Hour(dtLocal3.AddHours(1))
Dim kind3 = dtUTC3.Kind
printDate(dtUTC3, dtLocal3, iHoraIn3, kind3)
End Sub
Sub printDate(ByVal dtUtc, ByVal dtLocal, ByVal hora, ByVal utcKind)
System.Console.WriteLine("UTC: {0}, UTC KIND: {1}, LOCAL: {2}, HORA: {3}", dtUtc, utcKind, dtLocal, hora)
End Sub
The above produces this output:
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Local, LOCAL: 2013-10-26 09:33:00 PM, HORA: 22
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Local, LOCAL: 2013-10-26 09:33:00 PM, HORA: 22
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Utc, LOCAL: 2013-10-26 11:33:00 PM, HORA: 0
So what you are seeing is not a bug - it is expected behavior. You are trying to convert what you think is a UTC Date; however in reality it is really a local date.
I believe what you are expecting to see is what happens in the third code block above. It creates a UTC date and converts it to local time.
what happen here is
Sub Main()
Dim valor = "2013-10-26T19:33Z"
'this convert to local time
Dim dtUTC = CDate(valor)
'this add one hour to local time in 24 hour format
'equal to dtUTC.AddHours(1).Hour
Dim iHoraIn = dtUTC.ToLocalTime.AddHours(1).Hour
End Sub
2013-10-26T19:33Z is 2013-10-26 15:33 in my time zone, dtUTC show this time
i'm adding 1 hour to it so iHoraIn is now 16
in your screenshot, the watch show dtUTC as 9:33 PM which is 21 hour
you add 1 hour which now is 22 hour
is this what you expect?

OData4j exceptions - "Odd number of characters" and "bad valueString part of keyString"

EDIT:
The solution was to make a view that mirrored the table in question and converted the date to varchar and then convert it back to date with a matching collation
END OF EDIT
Can anyone tell me why OData4j reads datetime values fine from one of my WCF Data Service server but runs into an illegal argument exception (bad valueString as part of keyString) when reading exact same datetime type with same format from another WCF Data Service?
java.lang.IllegalArgumentException: bad valueString
[datetime'2012-01-24T14%3A57%3A22.243'] as part of keyString
The other problem is that when I ask for a JSON response from the service from which OData4j had no problem reading datetime types I get another illegal argument exception and the error message is - Odd number of characters.
java.lang.IllegalArgumentException:
org.odata4j.repack.org.apache.commons.codec.DecoderException: Odd
number of characters.
Because WCF Data Services can't have multiple sources, I've made 2 projects with each it's own Entity Data Model source (from existing database). And like I mentioned above, I'm getting these annoying errors.
To conclude...
Example 1: bad valueString as part of keyString - when reading datetime. Also happens with FormatType.JSON.
ODataConsumer customerInfoServices = ODataConsumer
.newBuilder("http://10.0.2.2:41664/CustomerInfoWCFDataServices.svc/")
.setFormatType(FormatType.ATOM)
.build();
customer = customerInfoServices
.getEntities("Customers")
.select("name, id")
.filter("id eq " + 5)
.execute()
.firstOrNull();
Example 2: Odd number of characters. Only happends with FormatType.JSON and no problem reading datetime.
ODataConsumer businessServices = ODataConsumer
.newBuilder("http://10.0.2.2:35932/BusinessWCFDataServices.svc/")
.setFormatType(FormatType.JSON)
.build();
Enumerable<?> ordrer = businessServices
.getEntities("Orders")
.filter("custId eq " + customer.getProperty("id").getValue())
.execute();
What I want is to receive JSON responses (ATOM is still too bloaded for android) and no problems reading datetime properties.
No body able to help me?
I've been wearing my fingers down trying to find a solution on Google, without any luck.
The collation on the database without datetime problems is "Danish_Norwegian_CI_AS" and on the database with reading errors is "SQL_Danish_Pref_CP1_CI_AS". I don't know if this has any meaning but I have a suspescion it has something to do with it.
The solution was to make a view that mirrored the table in question and converted the date to varchar and then convert it back to date with a matching collation. :-)
I ran into this issue today, and after running around for about three hours Googling and looking at code I managed to figure out what is going on. Here's my setup/situation and what I found:
The Setup
(OData Service) Microsoft IIS 8.0 on Windows Server 2012 using
default application pool.
(OData Producer) Microsoft WCF middle-tier
using Entity Framework and Web Data Services.
(OData Consumer)
Android client using OData4J v0.8 SNAPSHOT.
The Problem
In my Middle-tier (the OData Producer) I am using Entity Framework 5.0 to define a simple table with an Edm.DateTime column. My MessageTable.edmx file generates a simple table:
CREATE TABLE [dbo].[MessageTable] (
[Id] int IDENTITY(1,1) NOT NULL,
[Date1] datetime NULL
);
In my middle-tier's WCF data service (OData Producer) I intercept the OData POST from my Android client application. I manually set the Date1 column in the middle-tier using some C# code:
private static void ProcessMessage(ODataMessage message)
{
.
.
.
conn.Open();
cmd.ExecuteNonQuery();
int returnCode = (int)cmd.Parameters["#result"].Value;
if (returnCode == 0)
{
message.Processed = true;
message.Date1 = DateTime.Now;
}
.
.
.
}
Notice that I used C#'s DateTime.Now static property. The MSDN documentation states that DateTime.Now:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.
The key thing to realize is that local time means the C# date-time structure now includes local time zone information.
So, after the middle-tier code finishes, the WCF service inserts the OData POST into my table. Microsoft then sends the [Date1] column back to my Android client (the OData Consumer). It appears that Microsoft encodes the date as an OData DateTimeOffset because it includes local time-zone information. I.e. as 2013-08-26T17:30:00.0000000-7:00
The Code
In OData4j there is a package org.odata.internal that handles parsing OData date-time strings. In version 0.6 I found the following comment on lines 40-44 about the DATETIME_PATTERN regex pattern used to parse date-time strings:
40 // Since not everybody seems to adhere to the spec, we are trying to be
41 // tolerant against different formats
42 // spec says:
43 // Edm.DateTime: yyyy-mm-ddThh:mm[:ss[.fffffff]]
44 // Edm.DateTimeOffset: yyyy-mm-ddThh:mm[:ss[.fffffff]](('+'|'-')hh':'mm)|'Z'
45 private static final Pattern DATETIME_PATTERN =
46 Pattern.compile("(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(:\\d{2})?(\\.\\d{1,7})?((?:(?:\\+|\\-)\\d{2}:\\d{2})|Z)?");
47
48
In OData4j v0.7 the DATETIME_PATTERN has become DATETIME_XML_PATTERN:
40
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "(Z)?" + // group 4 (tz, ignored - handles bad services)
47 "$");
48
49 private static final Pattern DATETIMEOFFSET_XML_PATTERN = Pattern.compile("" +
50 "^" +
51 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})" + // group 1 (datetime)
52 "(\\.\\d{1,7})?" + // group 2 (nanoSeconds)
53 "(((\\+|-)\\d{2}:\\d{2})|(Z))" + // group 3 (offset) / group 6 (utc)
54 "$");
I think the comment on line 46 explains everything:
... // group 4 (tz, ignored - handles bad services)
I interpret this as saying 'Any time zone information is going to be ignored - this handles bad services (i.e. Microsoft) that send time zone info'
It appears to me that the OData4j authors have decided to stick to their guns and only accept the correct Edm.DateTime string format.
The Solution
The fix is very simple if you have access to the OData Producer code:
private static void ProcessMessage(ODataMessage message)
{
.
.
.
conn.Open();
cmd.ExecuteNonQuery();
int returnCode = (int)cmd.Parameters["#result"].Value;
if (returnCode == 0)
{
message.Processed = true;
message.Date1 = DateTime.UtcNow;
}
.
.
.
}
Use the DateTime.UtcNow property instead. The MSDN documentation states:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC).
If you do not have access to the OData producer, the only solution I can see is to change the OData4j code. Alter the regex pattern for DATETIME_XML_PATTERN:
41 private static final Pattern DATETIME_XML_PATTERN = Pattern.compile("" +
42 "^" +
43 "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})" + // group 1 (datetime)
44 "(:\\d{2})?" + // group 2 (seconds)
45 "(\\.\\d{1,7})?" + // group 3 (nanoseconds)
46 "((?:(?:\\+|\\-)\\d{2}:\\d{2})|Z)?" +
47 "$");
Conclusion
I think this is actually a mistake on Microsoft's part. I'm sure they have some involved justification for sending an Edm.DateTimeOffset but my MessageTable.edmx file specifies [Date1] as an Edm.DateTime, so I think that the Microsoft code should either do the conversion to UTC for me, or throw an exception. An exception would have warned me that I was using an incorrect DateTime structure and helped me see the DateTime.UtcNow solution much quicker.