The method to find absolute paths in the C language.

Preface

Recently, due to a last-minute client request, we need to modify all previously relative path references to absolute paths. Upon investigation, it appears that this can only be accomplished using Windows API for composition. However, our development tools are restricted to using C only, and the use of C++ syntax results in compilation errors. Therefore, we will employ a special string manipulation method to assist everyone in creating a way to find absolute paths.

Relative Paths

Here, we introduce the concept of relative positioning, which is relatively simple to write and only requires establishing a reference point from the executable file’s location for operation. As seen here, the search starts from the location of the .exe executable file to locate the corresponding reference.

 const char* infFilePath = "./Driver/STM32Bootloader.inf";
char command1[512];
 snprintf(command1, sizeof(command1), "start /MIN cmd.exe /C \"pnputil -i -a %s\"", infFilePath);

However, using relative positioning may result in issues when executing the program from other locations, as the surrounding relative positions may not be properly executed due to the inability to locate the path. Therefore, if there is a need to reference from other paths or to open the executable file from a different directory via the CMD method, it is necessary to switch to absolute positioning.

Absolute Paths


Absolute Paths In order to utilize absolute positioning, we need to employ the Windows API. However, implementing this purely in C can be somewhat challenging. The main functions used for this purpose are GetModuleHandleEx and GetModuleFileName, which allow us to obtain the absolute path of the current executable. However, this path includes the name of the executable itself, so we need to remove the executable name. Nevertheless, some projects do not support C++, so PathRemoveFileSpec may not be available. Below is a small example snippet to find the absolute path.

HMODULE hModule = NULL;// for get file path
	int iLength;
	// Initialize a file name, and New a logfile
	memset(g_filename, 0, sizeof(g_filename)); //filename
	 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)HPFI_Initialize, &hModule) == 0) {
        int ret = GetLastError();
       // logToFile( "[HPFI_Initialize]INFO:GetModuleHandle failed, error = %d", ret);
        // Return or however you want to handle an error.
    }

    if (GetModuleFileName(hModule, szEntryDirectory, MAX_PATH) == 0) {
        int ret = GetLastError();
        //logToFile( "[HPFI_Initialize]INFO:GetModuleFileName failed, error = %d", ret);
        // Return or however you want to handle an error.
    }

The resulting diagram is as follows:

Removing the Executable String

Here, two methods are provided. The first method involves using the C++ Windows API.

    TCHAR szEntryDirectory[MAX_PATH];
    HMODULE hModule = NULL;
    if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)HPFI_GetPackagedFirmwareInfo, &hModule) == 0) {
        int ret = GetLastError();
        fprintf(stderr, "GetModuleHandle failed, error = %d\n", ret);
        // Return or however you want to handle an error.
    }
    if (GetModuleFileName(hModule, szEntryDirectory, MAX_PATH) == 0) {
        int ret = GetLastError();
        fprintf(stderr, "GetModuleFileName failed, error = %d\n", ret);
        // Return or however you want to handle an error.
    }
    if(PathRemoveFileSpec(szEntryDirectory) == 0)
        fprintf(stderr, "PathRemoveFileSpec failed!!\n");

The second method requires first converting to char before operating. Essentially, it involves locating the position of the keyword and then copying it to a new area, trimming off the unnecessary parts.

  char *pch;
      pch = strstr(moduleFileName, "\\Firmware");
     // logToFile("[HPFI_Initialize]INFO: found at %d ",(pch-moduleFileName+1));
    strncpy(moduleFilepath, moduleFileName, (pch-moduleFileName));
    moduleFilepath[(pch-moduleFileName+1)]='\0';

Leave a Comment

Your email address will not be published. Required fields are marked *

Shopping Cart