We actually ran into some similar issues figuring this one out for ourselves, so hopefully I can shed some light on a few things.
First, as far as I can tell there is no way in current core Epicor to add new menus to the database tables. The GetNew and Update methods aren’t implemented, and the UpdateMenuData method looks like it is designed to handle the security data for the MES Menus (stored in the MESMenuSecurity table) rather than updating the MESMenu table. The error message you’re seeing is actually tied to the “System Setup > Security Maintenance > Handheld / MES Menu Security Maintenance” program which was added in 10.2 to manage the menu options based on employee security.
To add the menu items, I added them to the MESMenu EpiDataView in the transaction. This also involved filling in the security settings for the program, and specifying whether or not the current employee had access to the menu. Here’s a snip:
edvMenu = (EpiDataView)oTrans.EpiDataViews["MESMenu"];
if (edvMenu.dataView.Table.Select("MESMenuID = 700").Length <= 0)
row = edvMenu.dataView.Table.NewRow();
// Menu Setup
row["Company"] = ((Session)oTrans.Session).CompanyID;
row["MESMenuID"] = 700;
row["ParentMESMenuID"] = 1;
row["MenuType"] = "H";
row["Seq"] = 7;
row["MenuID"] = "HHMENUID";
row["MenuDesc"] = "Menu Title"; // Seq property is appended to start of menu title by default now.
row["Hidden"] = false;
row["SystemFlag"] = false;
// Employee Security
row["MESMaterialHandler"] = true;
row["MESSupervisor"] = true;
row["MESShipping"] = true;
row["MESProduction"] = true;
row["MESService"] = true;
row["PCIDInbound"] = false;
row["PCIDOutbound"] = false;
row["PCIDInventory"] = false;
row["PCIDManufacturing"] = false;
row["PCIDQuality"] = false;
row["CurrentEmpAllowed"] = ValidateEmpPermissions(dsEmpBasic.EmpBasic.Rows, row);
row["TranslateMenuDesc"] = "Menu Title";
row["BitFlag"] = 0;
row["RowMod"] = "";
ValidateEmpPermissions just compares the current employee’s settings against the menu’s security options, and returns true if the employee should be allowed to access the menu. I can send you code for this as well if you’d like.
As for timing, we call this both at the end of the InitializeCustomCode method and in an AfterAdapterMethod event handler, for the GetMenuData method. We also only load the custom menus if there is an employee ID specified (since in Epicor 10.2, the menus aren’t shown unless an employee is entered).
The only thing with this is that I haven’t figured out yet how to get a custom menu to show in the initial menu when the program first loads. If you open any of the other menus and then return to the main menu, your custom menu will show up at that point.