-2

When I call the Created method it crashes my console application. If I have it commented it out my program runs fine. I am trying to obtain the created date for a file on a shared network drive (Windows OS) and I cannot figure out what the error is. I just want to be able to obtain the timestamp for when a file was created. If I can fix this method to do that it's great. If not, any replacement method that will produce the timestamp of when that file was created is just as acceptable. Any help or direction is greatly appreciated.

#pragma comment(lib, "th32.lib")
#define VC_EXTRALEAN
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <cstring>
#include <io.h>
//#include <dirent.h>
#include <stdio.h>
#include <shlwapi.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <strsafe.h>
using namespace std;

//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
    //Get the error message, if any.
    DWORD errorMessageID = ::GetLastError();
    if(errorMessageID == 0)
        return std::string(); //No error message has been recorded

    LPSTR messageBuffer = nullptr;
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                                 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message.c_str();
}

__int64 FileSize(const wchar_t* name) //, bool _true
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    std::wstring temp;
    wchar_t* created;
    wchar_t* error;

    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
    {
        error = L"Error";
        return -1; // error condition, could call GetLastError to find out more
    }

    LARGE_INTEGER size;
    size.HighPart = fad.nFileSizeHigh;
    size.LowPart = fad.nFileSizeLow;
    //return (wchar_t*) size.QuadPart;
    return size.QuadPart;
}

const wchar_t* Created(const wchar_t* name) //, bool _true
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    //std::wstring temp;
    std::wstring created;
    SYSTEMTIME st;

    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
    {
        std::wstring error(L"Error");
        return error.c_str(); // error condition, could call GetLastError to find out more
    }

    if (!FileTimeToSystemTime(&fad.ftCreationTime, &st))
    {
        std::wstring error(L"Error getting created Time");
        return error.c_str(); // error condition, could call GetLastError to find out more
    }
    std::wstring month((wchar_t*)st.wMonth);
    std::wstring day((wchar_t*)st.wDay);
    std::wstring year((wchar_t*)st.wYear);
    created = month + L"/" + day + L"/" + year;
    //created = temp.c_str();
    //created = st.wMonth + '/' + st.wDay + '/' + st.wYear;


    return created.c_str();
}

int _tmain(int argc, _TCHAR* argv[])
{   
    std::wstring ap(L"//S001E002/Some Folder/");
    std::wstring all(L"*");
    std::wstring temp = ap + all;
    const wchar_t* Hotels = temp.c_str();
    const wchar_t* current = L".";
    const wchar_t* parent = L"..";
    wchar_t* pdf = L"/*.??f\0";
    wchar_t* tif = L"/*.*f";

    WIN32_FIND_DATA FindFileData;
    std::vector<std::wstring> folders;
    std::vector<std::wstring> vs;
    HANDLE hFind;

    std::wcout << "Hotels Folder directory: " << Hotels << "\n";

    hFind = FindFirstFile(Hotels, &FindFileData);
    if (hFind != INVALID_HANDLE_VALUE) 
    {
        do {
            {   
                if(FindFileData.dwFileAttributes & _A_SUBDIR)
                {
                    temp = FindFileData.cFileName;
                    if ( wcscmp(temp.c_str(), current) == 0 ||  wcscmp(temp.c_str(), parent) == 0 ) {}
                    else
                    {
                        folders.push_back(FindFileData.cFileName);
                        std::wcout << "Folder: " << FindFileData.cFileName << "\n";
                        //std::wcout << " equal? " << current << " : " << temp << " : " << parent << "\n";
                    }
                }
            }
        } while (FindNextFile(hFind, &FindFileData));
        FindClose(hFind);
    }
    //std::wcout << "Folder: " << str << "\n";
    for (int i = 0; i < folders.size(); i++)
    {
        //folders[i]
        temp = ap + folders[i] + pdf;
        const wchar_t* _files = temp.c_str();
        std::wcout << "File Directory: " << _files << "\n";
        hFind = FindFirstFile(_files, &FindFileData);
        if (hFind != INVALID_HANDLE_VALUE) 
        {
            do {
                {   
                    temp = FindFileData.cFileName;
                    if ( wcscmp(temp.c_str(), current) == 0 ||  wcscmp(temp.c_str(), parent) == 0 ) {}
                    else
                    {
                        //std::wcout << "File: "<< FindFileData.cFileName ;
                        //std::wcout << " equal? " << current << " : " << temp << " : " << parent << "\n";
                        temp = ap + folders[i] + L"/" + FindFileData.cFileName;
                        vs.push_back(temp); 
                    }
                }
            } while (FindNextFile(hFind, &FindFileData));
            FindClose(hFind);
        }
        else 
        {
            temp = ap + folders[i] + L"/";
            std::wcout << temp.c_str() << " | ";
            std::cout << GetLastErrorAsString() << "\n";
        }
    }

    /*for (auto item : vs)
        std::wcout << item << "\n";*/
    __int64 size;
    const wchar_t* created;
    std::cout << "\n" << "Start File Stats" << "\n";
    for (int i = 0; i < vs.size(); i++)
    {
        size =  FileSize(vs[i].c_str());
        created = Created(vs[i].c_str());
        std::wcout << vs[i] << " | File size: ";
        std::wcout << size ;
        std::wcout << " | Created: " << created << " | Error: " << GetLastErrorAsString; 
        std::wcout << "\n"; // , 1 << FileSize(vs[i].c_str(), 0)
    }

    std::cout << "\n" << "End File Stats" << "\n";
    std::cout << GetLastErrorAsString() << "\n";
    std::cout << "Folder count: " << folders.size() << "\n";
    std::cout << "File   count: " << vs.size() << "\n";
    return 0;
}
MM4100
  • 33
  • 4
  • we don't even have the _full_ method. And the execution trace (since you added a lot of traces, they could be useful). Wait: the debugger is even more useful. – Jean-François Fabre Oct 21 '16 at 20:50
  • 1) I would use wstringstream to build the string. 2) You are returning a local variable. 3) Can't you narrow down to which line is causing the crash? – 001 Oct 21 '16 at 20:54
  • @JohnnyMopp The following line is where the error occurs. if (!FileTimeToSystemTime(&fad.ftCreationTime, &st)) { std::wstring error(L"Error getting created Time"); return error.c_str(); // error condition, could call GetLastError to find out more } – MM4100 Oct 21 '16 at 22:08
  • @JohnnyMopp putting it in a If statement avoids the crash now but I am unable to get an error code. I call GetLastErrorAsString() but it doesn't have an error to return. All I really want is a method to retrieve the file created timestamp. – MM4100 Oct 21 '16 at 22:10
  • @Jean-FrançoisFabre I added the "Full Program" that contained the "full method". You seem to pretty familiar to c++, I am pretty new myself, the debugger offered little help to me maybe you'll find something. I care more to find a method that will retrieve the date created for me than to fix this method honestly. – MM4100 Oct 21 '16 at 22:14
  • 2
    You're returning a pointer to an error string that has been destroyed once you return from the function. Don't do that! I'd suggest returning `std::wstring` instead of `const wchar_t*` – Mark Ransom Oct 21 '16 at 22:15
  • @MarkRansom Oh okay will be that change right away. I am pretty new to c++ so I really appreciate your tip. Thank you. – MM4100 Oct 21 '16 at 22:18
  • I would suggest taking a look at [this](http://stackoverflow.com/a/4643721/5386374) post, which explains why you don't return a reference or pointer to a local variable. While the question and answer are about returning references to temporary objects, the same thing happens when you return a pointer to a temporary object. – Justin Time - Reinstate Monica Oct 21 '16 at 22:32

1 Answers1

0
std::wstring month((wchar_t*)st.wMonth);
std::wstring day((wchar_t*)st.wDay);
std::wstring year((wchar_t*)st.wYear);
created = month + L"/" + day + L"/" + year;

You cannot use casting to convert integer to string. These two data types are very different. You could use casting to convert int to double etc. but not this. Use std::to_wstring instead. Remove reference to c_str for error strings and created, so you have

std::wstring created =
    std::to_wstring(st.wMonth) + L"/" +
    std::to_wstring(st.wDay) + L"/" +
    std::to_wstring(st.wYear);

GetLastErrorAsString() returns ANSI string, while the rest of the program is in Unicode. You try to fit it in by using the following:

std::wcout << GetLastErrorAsString << "\n"; <== error

But the result is meaningless. You should make everything Unicode. Also, GetLastErrorAsString should not return .c_str()

Moreover, do not call GetLastError() unless the function fails or if documentation indicates that calling GetLastError() is useful.

if (FindFileData.dwFileAttributes & _A_SUBDIR)

The correct flag to use here is FILE_ATTRIBUTE_DIRECTORY. See File Attribute Constants


__int64 FileSize(const wchar_t* name)
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
        return -1; 

    LARGE_INTEGER size;
    size.HighPart = fad.nFileSizeHigh;
    size.LowPart = fad.nFileSizeLow;
    return size.QuadPart;
}

std::wstring Created(const wchar_t* name)
{
    WIN32_FILE_ATTRIBUTE_DATA fad;
    std::wstring created;
    SYSTEMTIME st;

    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
    {
        std::wstring error(L"Error");
        // error condition, could call GetLastError to find out more
        return error; 
    }

    if (!FileTimeToSystemTime(&fad.ftCreationTime, &st))
    {
        std::wstring error(L"Error getting created Time");
        // error condition, could call GetLastError to find out more
        return error; 
    }

    created =
        std::to_wstring(st.wMonth) + L"/" +
        std::to_wstring(st.wDay) + L"/" +
        std::to_wstring(st.wYear);
    return created;
}

int main()
{
    std::wstring ap(L"//S001E002/Some Folder/");
    std::wstring all(L"*");
    std::wstring temp = ap + all;
    const wchar_t* Hotels = temp.c_str();
    wchar_t* pdf = L"/*.??f\0";

    WIN32_FIND_DATA FindFileData;
    std::vector<std::wstring> folders;
    std::vector<std::wstring> vs;
    HANDLE hFind;

    std::wcout << "Hotels Folder directory: " << Hotels << "\n";

    hFind = FindFirstFile(Hotels, &FindFileData);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do 
        {
            if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if (wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0)
                    continue;
                folders.push_back(FindFileData.cFileName);
                std::wcout << "Folder: " << FindFileData.cFileName << "\n";
            }
        } while (FindNextFile(hFind, &FindFileData));
        FindClose(hFind);
    }

    for (int i = 0; i < (int)folders.size(); i++)
    {
        temp = ap + folders[i] + pdf;
        const wchar_t* _files = temp.c_str();
        std::wcout << "File Directory: " << _files << "\n";
        hFind = FindFirstFile(_files, &FindFileData);
        if (hFind != INVALID_HANDLE_VALUE)
        {
            do 
            {
                if (wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0)
                    continue;
                temp = ap + folders[i] + L"/" + FindFileData.cFileName;
                vs.push_back(temp);
            } while (FindNextFile(hFind, &FindFileData));
            FindClose(hFind);
        }
        else
        {
            temp = ap + folders[i] + L"/";
            std::wcout << temp.c_str() << "\n";
        }
    }

    __int64 size;
    std::cout << "\n" << "Start File Stats" << "\n";
    for (int i = 0; i < (int)vs.size(); i++)
    {
        size = FileSize(vs[i].c_str());
        std::wstring created = Created(vs[i].c_str());
        std::wcout << vs[i] << " | File size: ";
        std::wcout << size;
        std::wcout << " | Created: " << created;
        std::wcout << "\n";
    }

    std::cout << "\nEnd File Stats" << "\n";
    std::cout << "Folder count: " << folders.size() << "\n";
    std::cout << "File   count: " << vs.size() << "\n";
    return 0;
}

A better way to format date/time is using std::stringstream

//additional headers
#include <sstream>
#include <iomanip>

...
std::wostringstream oss;
oss << std::setfill(L'0');
oss 
    << st.wMonth << L"/" 
    << st.wDay << L"/" 
    << st.wYear << L" " 
    << std::setw(2) << st.wHour << L":" 
    << std::setw(2) << st.wMinute << L":" 
    << std::setw(2) << st.wSecond;
created = oss.str();

or you can use Windows date/time format:

wchar_t buf[100];
GetDateFormat(0, 0, &st, 0, buf, 100);
created = buf;
GetTimeFormat(0, 0, &st, 0, buf, 100);
created += std::wstring(L" ") + buf;
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Thank you so much this resolved my question. One thing to note for anyone reading this solution is that if your using visual studio 2010 like I am. There is a bug that requires the following: – MM4100 Oct 24 '16 at 15:10
  • created = std::to_wstring(static_cast(st.wMonth)) + L"/" + std::to_wstring(static_cast(st.wDay)) + L"/" + std::to_wstring(static_cast(st.wYear)) + L" " + std::to_wstring(static_cast(st.wHour)) + L":" + std::to_wstring(static_cast(st.wMinute)) + L":" + std::to_wstring(static_cast(st.wSecond)) + L":" + std::to_wstring(static_cast(st.wMilliseconds)); – MM4100 Oct 24 '16 at 15:11
  • See the following for a detailed explanation: http://stackoverflow.com/questions/10664699/stdto-string-more-than-instance-of-overloaded-function-matches-the-argument – MM4100 Oct 24 '16 at 15:14
  • I can't read the code in your comment. See updated answer for date/time format. – Barmak Shemirani Oct 25 '16 at 01:59
  • I see your updated answer. I thank you for your informative answer. It's very useful and avoids the workaround I had to use in my previous comment. The code in the comment you couldn't read, which I am unable to edit for some reason, required that you cast st into a type like so that it can then be converted into a wstring by use of std::to_wstring. This bug only affects users of Visual Studio 2010 but has since been fixed in Visual Studio 2012. – MM4100 Oct 25 '16 at 16:09