Search code examples
winformsc++-climarshalling

Application Logs | IP Address + Pointer Issues


I am very new to C++-CLI and recently finished working on my first "official" application. I was advised to create application logs to track its effectiveness. When the form opens, the application tracks the date, time, and PC username and writes it to a text file.

That works well, though I am having trouble displaying an IP Address. I receive an error "Type name is not allowed" on (System::Net::IPAddress).

            lastlineoffile += ( std::string((char *)Marshal::StringToHGlobalAnsi(DateTime::Now.ToString("MM-dd-yy")).ToPointer()) + "  "  + 
            std::string((char *)Marshal::StringToHGlobalAnsi(DateTime::Now.ToString("HH:mm")).ToPointer()) + "  " +
            //std::string((char *)Marshal::StringToHGlobalAnsi(System::Net::IPAddress).ToPointer()) + "  " +
            std::string((char *)Marshal::StringToHGlobalAnsi(System::Environment::UserName).ToPointer()) );
        std::cout << "last line to be added: " << lastlineoffile << std::endl;

        file << lastlineoffile.c_str();
        //saves usage text file
        file.close();

Additionally, I would like to record the time the application is exited. The previous perimeters are all recorded at the start of the application. I figure there would have to be a pointer that references the time off when the application closes. Any insight on how this would be accomplished would be appreciated.

Thanks


Solution

  • System::Net::IPAddress is the name of a class, not an object. It's a data storage class used for storing IP addresses. It's not an object you can pass to StringToHGlobalAnsi.

    I'm guessing that you want to log your machine's IP address. OK, but which one? The computer I'm on right now has 6 of them, and would have more if I connected to a VPN. I'd follow the instructions in this question & answer to iterate over the IP addresses, and pick one, but you'll still have multiple if you have multiple network cards, whether real or virtual.

    If all you need is a lightweight 'which machine is this' identifier, you may want to use Environment::MachineName. That will give you the current machine's name, as a string.

    Other notes:

    • Standard warning: While it's certainly possible to write the main body of your application in C++/CLI, or even write the GUI in C++/CLI using WinForms, it is not recommended. C++/CLI is intended for interop scenarios: where C# or other .Net code needs to interface with unmanaged C++, C++/CLI can provide the translation between the two. For primary development, it is recommended to use C# with either WinForms or WPF if you want managed code, or C++ with MFC if you want unmanaged.
      • Related to that, if you're writing C++/CLI, I would prefer to use the higher-level language when you have a choice. Therefore, I would favor the .Net File I/O, rather than unmanaged io streams. You're already writing managed code, with a very full-featured standard library, you might as well use it!
    • StringToHGlobalAnsi is not the preferred way to convert from managed to unmanged strings. If you do want to use it, that's fine, but each call without a corresponding call to FreeHGlobal is a memory leak. The preferred way is to use marshal_as, as described in Overview of Marshaling in C++. With marshal_as, you can convert directly from String^ to std::string, and both classes manage their memory appropriately, so no memory leaks. (But using the higher-level language, and doing your logging with .Net classes, would be even better.)