I want a piece of function which will take a file and last how many days, if it was older than that date, will return 0 otherwise 1... Something like that...
For example:
int IsOlder(TCHAR *filename, int days)
{
do operation.
If last modify date was older than days variable
return 0
else
return 1
}
It's MS VC++ 6 for Windows.
Thanks from now!
Windows has an API function called GetFileTime() (doc on MSDN) taking a file handle in parameter and 3 FILETIME structures to be filled with date-time info:
FILETIME creationTime,
lpLastAccessTime,
lastWriteTime;
bool err = GetFileTime( h, &creationTime, &lpLastAccessTime, &lastWriteTime );
if( !err ) error
The FILETIME structure is obfuscated, use the function FileTimeToSystemTime() to translate it to a SYSTEMTIME structure which is way easier to use:
SYSTEMTIME systemTime;
bool res = FileTimeToSystemTime( &creationTime, &systemTime );
if( !res ) error
Then you can use fields wYear, wMonth, etc. to compare with your number of days.
GetFileTime gets the various dates relevant to a file. There's an example.
You will need to fetch the last write time, and calculate the difference in days from there. As the GetFileTime function returns the quite unwieldy FILETIME structure you probably want to convert it into system time (struct SYSTEMTIME) with FileTimeToSystemTime.
Related
I've got an 8601 format time string like so:
std::string strTime("1601-01-01T00:01:53.537Z");
I want to increment the hour and change its value to
"1601-01-01T01:01:53.537Z"
I think the steps are: convert string to a time object, increment the hour by 1, convert the object back to a string.
Of course, it would be helpful if all the normal time considerations and boundaries were taken into account (such as adding an hour to 11:30 pm will move to the next day, etc...). I've been looking at strftime, strptime, std::get_time and others but have not been able to work it out yet.
I'm using VS2012 on Windows. Thanks.
Some pseudo code to get you started.
char *AddHour(char *dest, size_t size, const char *timestamp) {
Initialize struct tm
Scan timestamp into tm
Check scanning success
Check year range validity
Bring into range acceptable by mktime()
Add hour
Call mktime()
Undo range adjustment made beforehand
Print tm to dest
return dest;
}
Even though mktime() uses local timezone, by keeping the tm_isdst == 0 we can use this for the Z timezone (UTC) for all practical purposes.
Simply scan the string into various parts. Add 1 hour and then reform the string
string --> struct tm tm;
// Add hour
if (++tm.tm_hour >= 24) {
tm.tm_hour = 0;
if (++tm.tm_mday > EOM(tm.tm_year, tm.tm_mon)) {
tm.tm_mday = 1;
if (++tm.tm_mon > 12) {
tm.tm_mon = 1;
tm.tm_year++;
}
}
}
struct tm tm --> string
I have written a C library that parses and formats a ISO 8601 calendar date with time and zone designator in extended format. It's available on Github, c-timestamp.
{
timestamp_t ts;
char *str = "1601-01-01T00:01:53.537Z";
timestamp_parse(str, strlen(str), &ts);
ts.sec += 1*60*60;
timestamp_format(str, strlen(str), &ts);
puts(str);
}
I need to get the system current date format string like ("dd-mm-yyyy" , "mm/dd/yyyy" ect.
GetDateFormat() API returns the formatted string like "12-09-2015" but need string like "dd-mm-yyyy"
C# solution
string sysFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
But I need in Win32.
You can get a list of format strings currently applicable, by enumerating them. This is done through EnumDateFormats. Note, that there can be (and usually is) more than one, so you will have to decide, which one to pick1).
The following code returns the system's default short dateformat pattern:
static std::list<std::wstring> g_DateFormats;
BOOL CALLBACK EnumDateFormatsProc( _In_ LPWSTR lpDateFormatString ) {
// Store each format in the global list of dateformats.
g_DateFormats.push_back( lpDateFormatString );
return TRUE;
}
std::wstring GetShortDatePattern() {
if ( g_DateFormats.size() == 0 &&
// Enumerate all system default short dateformats; EnumDateFormatsProc is
// called for each dateformat.
!::EnumDateFormatsW( EnumDateFormatsProc,
LOCALE_SYSTEM_DEFAULT,
DATE_SHORTDATE ) ) {
throw std::runtime_error( "EnumDateFormatsW" );
}
// There can be more than one short date format. Arbitrarily pick the first one:
return g_DateFormats.front();
}
int main() {
const std::wstring strShortFormat = GetShortDatePattern();
return 0;
}
1) The .NET implementation does the same thing. From its list of candidates, it arbitrarily picks the first one.
You can use time function together with localtime function.
Example code:
//#include <time.h>
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
//The years are since 1900 according the documentation, so add 1900 to the actual year result.
char cDate[255] = {};
sprintf(cDate, "Today is: %d-%d-%d", timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year + 1900);
I want to get the install date of product:
DWORD max = 255;
WCHAR buffer[255];
std::wstring guidWString = S::WstrToStr(subKeys[i]); //from array of std::string
LPCWSTR guid = guidWString.c_str();
int err = MsiGetProductInfo(guid, INSTALLPROPERTY_INSTALLDATE, buffer, &max);
if(err == ERROR_SUCCESS){ //never success :(
info.date = S::WstrToStr(std::wstring(buffer));
}
But I always get the error code 87 (*ERROR_INVALID_PARAMETER*).
I don't see anything "invalid" here, according to the documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa370130%28v=vs.85%29.aspx
I have checked that:
All variables are of good types, buffer size (DWORD max) is not null, equal to the size of my buffer.
I use a function to convert std::string (I have my GUID in std::string) to std::wstring (under debugger, all looks good, conversion works in many other places in code that use WinAPI and std::wstring).
I have tried with different GUID, all of them exists and works for asking register "manually". MsiGetProductInfo() returns that error ALWAYS.
I have also tried to just write GUID in code (L"{GUID-GO-EXACTLY-HERE}"), with the same result.
I just don't know where the problem is?
I was writing a quick utility to dump out some of the details of the stat structure but hit an issue as the time attributes of stat seem to be of type timestruc_t which on my platform seems to be two 64bit ints.
struct stat statBuf;
return_code = stat( aFileName, &statBuf );
if ( !return_code )
{
struct tm res;
localtime_r( statBuf.st_mtim.tv_sec, &res ); // problem!
I thought I could maybe use localtime_r to convert the seconds attribute into a struct tm but I seem to get casting issues using statBuf.st_mtim.tv_sec as the first parameter.
I'm sure this isn't the best solution - maybe you know a better one. I just want to get the date and time - down to sub-seconds if possible - out as a string in the format YYYY-MM-DD HH.MM.SS.SSS or something similar. Any suggestions would be very welcome.
UPDATE
This was a simple issue - my mistake. Just forgot that the first parameter needs to be the address of and int not the int by value. So the amended and partially completed code looks like this:
localtime_r( &statBuf.st_mtim.tv_sec, &res );
const int bufLen=24;
char buffer[ bufLen + 1];
strftime( buffer, bufLen, "%Y-%m-%d %H:%M:%S", &res );
printf(" %s, %s\n", aFileName, buffer);
The first parameter needs to be the address of an int not the int by value.
The following piece of code seems to unreliably execute and after and undeterministic time it will fail with error code 234 at the RegEnumValue function.
I have not written this code, I am merely trying to debug it. I know there is an issue with doing RegEnumValue and then deleting keys in the while loop.
I am trying to figure out first, why it is throwing this 234 error at seemingly random points, as in, it is never after a consistent number of loop iterations or anything like that.
From what I have seen it fails to fill its name buffer, but this buffer is by no means too small for its purpose, so I don't understand how it could fail??
Could someone please advice on getting rid of this 234 error thrown by the RegEnumValue funciton?
HKEY key;
DWORD dw;
int idx;
char name[8192];
DWORD namesize=4096;
std::string m_path = "SOFTWARE\\Company\\Server 4.0";
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,m_path.c_str(),0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS)
{
bool error=false;
idx=0;
long result;
long delresult;
while (true)
{
result = RegEnumValue(key,idx,(char*)name,&namesize,NULL,NULL,NULL,NULL);
if (result == ERROR_SUCCESS && !error){
delresult = RegDeleteValue(key,name);
if (delresult != ERROR_SUCCESS)
error = true;
idx++;
}
else
{
break;
}
}
RegCloseKey(key);
}
There are some errors in your code:
The 4-th parameter of RegEnumValue (the namesize) is in-out parameter. So you have to reset namesize to sizeof(name)/sizeof(name[0]) (in case of the usage char type it is just sizeof(name)) inside the while loop before every call of RegEnumValue. It's the main error in your program.
If you don't want to have ERROR_MORE_DATA error any time you have the buffer having 32,767 characters. It is the maximum size of name the the regitry value (see documentation of RegEnumValue).
It is not good to use KEY_ALL_ACCESS in the RegOpenKeyEx. I'll recomend you to change it to KEY_QUERY_VALUE | KEY_SET_VALUE. It is not a real error, but depends on your environment it could be.
It if better to use UNICODE version of all this functions to speed-up a little the code.
UPDATED: Only small comment about the usage of the UNICODE version. Intern Windows work with UNICODE characters. So usage of non-Unicode version of RegEnumValue si more slow because at the evry call a new UICODE memeory block will be allocated and converted to ANSI/Multi-byte. Moreover if you will has a value name written in a language which can't be converted in you Windows ANSI code page (Chinese, Japanese and so on) and some characters will be replaced to '?' (see WC_DEFAULTCHAR flag of WideCharToMultiByte), then it can be that the function RegDeleteValue will fail with the error code like "the value with the name is not exist".
just change the value of your fourth parameter i.e namesize from 4096 to 8192 .Always MakeSure that it should be always equal to buffer size.
The answer is at the bottom of that page:
http://msdn.microsoft.com/en-us/library/ms724865(VS.85).aspx
Please read the answer of "ERROR_MORE_DATA: lpData too small, or lpValueName too small?" question.