Creating DLL for ShellExecute
Good afternoon,
As titled, I am crafting a general purpose ShellExecute that will run inside Prime. I have it working. But there is an issue with a null pointer.
My approach was to pass strings. These are strings that define the EXE, and the command line.
An example would be like this:
ShellExecute ("Notepad.exe", "c:\\data\\test.txt", "Null")
The problem is that I had an issue with a null pointer being passed, so I had to create three MCAD strings like this:
LRESULT ShellExecute_MCAD(MCSTRING* pMCS_Empty, MCSTRING* pMCS_Process_EXE, MCSTRING* pMCS_Process_CMD)
here is the Visual Studio cpp file. I can also attach it if needed.
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "MCADINCL.H"
LRESULT ShellExecute_MCAD(MCSTRING* pMCS_Empty, MCSTRING* pMCS_Process_EXE, MCSTRING* pMCS_Process_CMD)
{
// Routine performs a MCAD shell execute
HINSTANCE L_Result = 0;
wchar_t LpA_Process_EXE[MAX_PATH];
wchar_t LpA_Process_CMD[MAX_PATH];
wchar_t LpA_Empty[MAX_PATH];
char pA_Process_EXE[MAX_PATH] = "";
char pA_Process_CMD[MAX_PATH] = "";
char pA_Empty[MAX_PATH] = "";
// Define char arrays for process name and file name for process
strcpy_s(pA_Process_EXE, pMCS_Process_EXE->str);
strcpy_s(pA_Process_CMD, pMCS_Process_CMD->str);
//strcpy_s(pA_Empty, pMCS_Empty->str);
// Derived from https://cplusplus.com/forum/beginner/23378/
std::copy(pA_Process_EXE, pA_Process_EXE + lstrlenA(pA_Process_EXE) + 1, LpA_Process_EXE);
std::copy(pA_Process_CMD, pA_Process_CMD + lstrlenA(pA_Process_CMD) + 1, LpA_Process_CMD);
std::copy(pA_Empty, pA_Empty + lstrlenA(pA_Empty) + 1, LpA_Empty);
//MessageBox(NULL, LpA_Process_EXE, (LPCWSTR)L"MCAD ShellExecute EXE", MB_ICONINFORMATION);
//MessageBox(NULL, LpA_Process_CMD, (LPCWSTR)L"MCAD ShellExecute CMD", MB_ICONINFORMATION);
//MessageBox(NULL, LpA_Empty, (LPCWSTR)L"MCAD ShellExecute Empty", MB_ICONINFORMATION);
//MessageBox(NULL, (LPCWSTR)L"Preparing a test of ShellExecute", (LPCWSTR)L"MCAD ShellExecute", MB_ICONINFORMATION);
L_Result = ShellExecute(NULL, TEXT("open"), LpA_Process_EXE, LpA_Process_CMD, NULL, SW_SHOWNORMAL);
// Return normal
return 0;
}
// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad
FUNCTIONINFO FI_ShellExecute_MCAD =
{
// Name by which mathcad will recognize the function
"ShellExecute",
// description of "shell" parameters to be used by the Insert Function dialog box
"S_Process_EXE, S_Process_CMD",
// description of the function for the Insert Function dialog box
"Routine runs performs ShellExecute with the command line",
// pointer to the executible code i.e. code that should be executed when a user types in "multiply(a,M)="
(LPCFUNCTION)ShellExecute_MCAD,
// ShellExecute(S, S) returns a string
STRING,
// ShellExecute(S, S) takes on two string arguments
3,
// The first is the executable name, the second is the command line
{STRING, STRING, STRING}
};
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CreateUserFunction(hModule, &FI_ShellExecute_MCAD);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// table of error messages if your function never returns an error
const char* myErrorMessageTable[NUMBER_OF_ERRORS] =
{ "interrupted",
"insufficient memory",
"must be real"
};
#undef INTERRUPTED
#undef INSUFFICIENT_MEMORY
#undef MUST_BE_REAL
#undef NUMBER_OF_ERRORS
When I run this, the only way this works is to place a sacrificial string at the end of the call. Here is a screenshot:

Can anyone provide guidance as to why this is happening.
Thank you.
Regards,

