Support Board
Date/Time: Fri, 17 Jan 2025 21:32:13 +0000
Sierra ARM64 version lag and extra x64 log messages on SierraChart_ARM64.exe
View Count: 74
[2025-01-17 01:24:25] |
User719512 - Posts: 287 |
Hello Sierra Chart Engineering, The ARM version of Sierra is not in sync for the current version nor pre-release. Installed v2732 and v2733 and Sierra for ARM64 is still v 2728. Is it possible to update your build/release process to release both x64 and ARM64 with the same versions all the time? Second, related to your previous cleanup of extraneous log messages for _ARM64 when running x64, can the extraneous messages for x64 dlls when running Sierra ARM64 builds be addressed as well? I have included a sample log file with some comments prefixed with "^^^" below. Similar to how the x64 version now disregards messages for ARM64 and does not try to load "_ARM64.dll" files, the corresponding change for ARM64 seems appropriate where Sierra for ARM64 should disregard and/or not load "_64.dll" files when using "Add Custom Study". Example log file from SierraChart_ARM64.exe: 2025-01-17 00:30:53.221 | Software version: 2728 64-bit ^^^ downloaded v2732 and v2733, and ARM version is not in sync with the x64 version ... 2025-01-17 00:31:05.140 | Found DLL: C:\SierraChart\Data\OrderFlowLabs.com.autoplot.dll 2025-01-17 00:31:05.140 | Found DLL: C:\SierraChart\Data\OrderFlowLabs.com.free.dll 2025-01-17 00:31:05.140 | Found DLL: C:\SierraChart\Data\OrderFlowLabs.com.dll 2025-01-17 00:31:05.156 | OrderFlowLabs.com.autoplot_64.dll loading error. Windows error code 193: %1 is not a valid Win32 application. ^^^ Sierra loads _ARM64 version of this dll 2025-01-17 00:31:05.159 | OrderFlowLabs.com.beta_64.dll loading error. Windows error code 193: %1 is not a valid Win32 application. 2025-01-17 00:31:05.159 | InternalVersionNumberToFileNameMap is empty for OrderFlowLabs.com.beta 2025-01-17 00:31:05.159 | Closest match search for: C:\SierraChart\Data\OrderFlowLabs.com.beta.dll returned empty result. * ^^^ an _ARM64 version of this dll is NOT present on the machine which gives 2 extra messages in this case. 2025-01-17 00:31:05.167 | OrderFlowLabs.com_64.dll loading error. Windows error code 193: %1 is not a valid Win32 application. ^^^ Sierra loads _ARM64 version of this dll 2025-01-17 00:31:05.172 | OrderFlowLabs.com.free_64.dll loading error. Windows error code 193: %1 is not a valid Win32 application. ^^^ Sierra loads _ARM64 version of this dll Since Sierra has a naming convention for its DLLs, name filtering/regex is probably sufficient rather than reading the IMAGE_DOS_HEADER, dosHeader.e_lfanew, PE Header and IMAGE_FILE_HEADER which has the Machine information. Thanks for taking a look at this. |
[2025-01-17 18:37:34] |
User719512 - Posts: 287 |
This message is to add clarity around reading the "source of truth" for determining the machine type rather than relying on the file name. I am certain the Sierra Engineering team know all this, so this post is aimed at the aspiring developers who were curious about reading machine information from a dll (or exe). This is a POC (proof of concept) demo app that shows machine information for dll or exe files. Could also be refactored into a library of course for other usage. #include <windows.h> #include <filesystem> #include <iostream> #include <regex> #include <string> #include <vector> namespace fs = std::filesystem; bool GetDLLArchitecture(const std::wstring& dllPath, WORD& machineType) { HANDLE file = CreateFile(dllPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (file == INVALID_HANDLE_VALUE) { std::wcerr << L"Failed to open file: " << dllPath << std::endl; return false; } // Read the DOS header IMAGE_DOS_HEADER dosHeader; DWORD bytesRead; if (!ReadFile(file, &dosHeader, sizeof(dosHeader), &bytesRead, nullptr) || bytesRead != sizeof(dosHeader)) { std::wcerr << L"Failed to read DOS header from: " << dllPath << std::endl; CloseHandle(file); return false; } if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { std::wcerr << L"Invalid DOS signature in: " << dllPath << std::endl; CloseHandle(file); return false; } if (SetFilePointer(file, dosHeader.e_lfanew, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { std::wcerr << L"Failed to seek to PE header in: " << dllPath << std::endl; CloseHandle(file); return false; } DWORD peSignature; if (!ReadFile(file, &peSignature, sizeof(peSignature), &bytesRead, nullptr) || bytesRead != sizeof(peSignature)) { std::wcerr << L"Failed to read PE signature from: " << dllPath << std::endl; CloseHandle(file); return false; } if (peSignature != IMAGE_NT_SIGNATURE) { std::wcerr << L"Invalid PE signature in: " << dllPath << std::endl; CloseHandle(file); return false; } IMAGE_FILE_HEADER fileHeader; if (!ReadFile(file, &fileHeader, sizeof(fileHeader), &bytesRead, nullptr) || bytesRead != sizeof(fileHeader)) { std::wcerr << L"Failed to read File Header from: " << dllPath << std::endl; CloseHandle(file); return false; } machineType = fileHeader.Machine; CloseHandle(file); return true; } std::wstring GetArchitectureName(WORD machineType) { switch (machineType) { case IMAGE_FILE_MACHINE_ARM64: return L"ARM64"; case IMAGE_FILE_MACHINE_AMD64: return L"x64"; case IMAGE_FILE_MACHINE_I386: return L"x86"; default: return L"Unknown"; } } void ProcessDLL(const std::wstring& dllPath) { WORD machineType; if (GetDLLArchitecture(dllPath, machineType)) { std::wcout << L"Architecture of " << dllPath << L": " << GetArchitectureName(machineType) << std::endl; } else { std::wcerr << L"Failed to determine architecture of: " << dllPath << std::endl; } } void ProcessDirectory(const std::wstring& directory, const std::wstring& pattern = L"*.dll") { std::wregex regex; bool useRegex = false; // Convert wildcard pattern to a regex if it contains '*' if (pattern.find(L'*') != std::wstring::npos) { std::wstring regexPattern = std::regex_replace(pattern, std::wregex(L"\\*"), L".*"); regex.assign(regexPattern, std::regex_constants::icase); useRegex = true; } // Iterate over files in the directory for (const auto& entry : fs::directory_iterator(directory)) { if (entry.is_regular_file()) { const auto& path = entry.path(); const std::wstring filename = path.filename().wstring(); // Match filename with the wildcard pattern if (useRegex) { if (std::regex_match(filename, regex)) { ProcessDLL(path.wstring()); } } else { if (filename == pattern) { ProcessDLL(path.wstring()); } } } } } int wmain(int argc, wchar_t* argv[]) { if (argc == 2 || argc == 3) { std::wstring input(argv[1]); // Check for wildcard usage if (argc == 3) { std::wstring pattern(argv[2]); if (fs::is_directory(input)) { ProcessDirectory(input, pattern); } else { std::wcerr << L"Invalid input: Wildcard requires a valid directory\n"; } } else if (fs::is_regular_file(input)) { ProcessDLL(input); } else if (fs::is_directory(input)) { ProcessDirectory(input); // Default to *.dll } else { std::wcerr << L"Invalid input: " << input << std::endl; } } else { std::wcout << L"Usage:\n" << L" <program> <dll-file> Process a single DLL file\n" << L" <program> <directory> [pattern] Process DLLs matching a wildcard pattern\n"; } return 0; } |
To post a message in this thread, you need to log in with your Sierra Chart account: