Best Practice to LaunchForm to Resolve Proper Menu ID


(Haso Keric) #1

I know many of us use LaunchForm or Context Menu Open With among other things. I thought I ask this question for all our sakes.

Lets say you have:

  • Production Management / General Operations / My Cool Dashboard [ UDB001 ] [ USEC001 ]
  • Sales Management / General Operations / My Cool Dashboard [ UDB002 ] [ USEC001 ]

Both have a Unique Menu ID, because they have to, however both share the Same Security ID. Because we will control the Sub-Folders who gets to see what.

So when you do LaunchForm you hardcode UDB001 for example. But what if the User does not have access to “Production Management”. I can’t recall properly but I could have sworn that it didn’t let me launch UDB001 in 10.1.500.x

But the User has UDB002 which is the same.

I have been thinking about this, but never dug deep into the research and I know Epicor has some helpers to find the proper Menu ID by looping through the MainForm Tree. Atleast I saw that in some .NET Reflecting. Anyone recall the helper class?

Basically sometimes I place a Dashboard or UD01 Table in 10 locations, so they are accessible and share the same Customization, but I don’t want to hardcode MENUID001 if the user only has MENUID009.

Maybe I did my test wrong and It will open it regardless of Parent Path having Access. I’ll test that again today; thought Id throw this out in-case someone else already has.

(Calvin Krusen) #2

I was under the impression that the Security on menus was strickly on their visibility.

Since the LaunchForm call isn’t accessing a menu, I’d assume menu security plays no role.

Am I wrong on this?

(Haso Keric) #3

If you do

ProcessCaller.LaunchForm(oTrans, "PJGO1010", lfo);

If the User does not have permissions to open PJGO1010 because it uses SEC18982; it will give you a MessageBox stating that you don’t have permissions. It happened to me also when the user did not have Persmissions to a Sub-Folder (Parent to the Menu).

So Hardcoding MenuID’s not cool. I have to test that in 10.2.300.

I did some initial research 3 months ago and found Epicor had some Helper Methods to basically locate an Alternative ID (basically looping through the Menu Tree until it Finds one you have access to). I need to review that again.

(Calvin Krusen) #4

I must have been thinking about “Open With…”

(Haso Keric) #5

Same with Open With… What if you create a Context Menu Entry for “UD001” but the user doesn’t have UD001 (because its Parent Folders) restrict the user…BUT he does have access to UD002 which is the same just another Path… Your Open with isn’t smart enough to figure it out :slight_smile:

Going to test this :slight_smile: I thought I did and failed. :smiley:

(Calvin Krusen) #6

Which menu does “Open With …” even use?

I did a quick test of adding a test user to the Disallowed Users of the Material Management menu. That user was still able to launch Part Entry from a Part field in a Sales Order Tracker.

Next I added that user to Disallowed Users of the Part Entry menu’s (MenuID: IMMT1102), Seurity (SecID:SEC159). User could still use “Open With…”

(Haso Keric) #7

Do you have a Custom Dashboard you can try it?

I think Epicor does not Hardcode their LaunchForms… Because they specify the Program, not the MenuID – So I assume it then “loops through” the Main Menu and finds the nearest avail MenuID because it needs to Honor your “Customizations”.

Community has been doing:

ProcessCaller.LaunchForm(oTrans, "PJGO1010", lfo);

Epicor Does:

ProcessCaller.LaunchForm(this, "Erp.UI.OrderHistoryEntry", opts);
ProcessCaller.LaunchForm(this, "Erp.UIRpt.ARInvForm", lfOpts);
ProcessCaller.LaunchForm(this, "Erp.UI.CustomerEntry", objlArgs);
ProcessCaller.LaunchForm(this, "Erp.UI.PartXRefSelectEntry", lfo);
ProcessCaller.LaunchForm(this, "Erp.UI.POSuggChgEntry", posArgs);

So should we be hardcoding MenuIDs in LaunchForm :slight_smile: or Specify the Program Name.

(Calvin Krusen) #8

If you specify the program name, can you include the which customization it should use?

(Haso Keric) #9

No, but I think the Process Caller tries to find the Nearest or First Menu it can find. So if you are Sharing Customizations lik

  • Quote Entry - Sales
  • Quote Entry - Tooling Department
  • Quote Entry - Dieshop

You might get a random one.

(Calvin Krusen) #10

After thinking about it for a bit, it seems like MenuID’s are “shorcuts”, that call pass the program name to launch.

Since you can restrict access to menus (aka the “shortcuts”), the security processes prevent the launch request from ever finding out which program to launch.

(Calvin Krusen) #11

I get an uneasy feeling when a function is not well defined in how it works. What is the algorithm used to “Find” the appropriate menu?

These kind of fuzzy operations tend to be ripe for exploiting.

(Haso Keric) #12

It looks at the ProcessXref.xml CustomContextMenu.xml and ProcessXrefCustom.xml in C:\ProgramData\Epicor Which are downloaded/synced during login.

Then it also uses stuff like

ProcessCaller.GetMenuProcess(sender, menuKey);
FormFunctions.GetMenuItemColumnValue(menuDS, "Arguments").ToString();
FormFunctions.GetArgumentValuePerToken(Arguments, "c");

The FormFunctions.GetMenuItem and Arguments I think help find that Menus args “Customization” etc…

Anyways. I’ll do some testing later on best way to use LaunchForm and to make sure I am not hardcoding myself to death… What if you delete “UD001” because you dont need it anymore… Do you want to keep a Spreadsheet to find all the Customizations where UD001 has to change to UD002 now? :slight_smile: probably not. So I think using the Program Name is probably better.

(Haso Keric) #13

I’ll check. These are important discussions especially once you start doing Multi-Company Menu Structures and Company Specific Securities.

(Calvin Krusen) #14

Would your custom code (that launches the form) have to do security checks then?

(Haso Keric) #15

No Epicor still handles that… By using

FormFunctions.CheckAppSecurity(string app, Session s);

Thus far what I believe happens is…

  1. Login as ckrusen
  2. Syncs Process, Context and other .xml’s based on Users “Security” and update xml’s in C:\ProgramData
  3. When using LaunchForms or Open With…
    3.1 Check if MenuID is in the .xml
    3.2 If LFO used ProgramName, find the MenuID in the .xmls
    3.3 IF IT Exists; Check Security; if Pass Launch?

(Calvin Krusen) #16

So you can’t launch a form by name if a Menu for it doesn’t exist?

If you can, then what does step 3 do when no menuID is found? That equals “don’t run” ??

(Haso Keric) #17

I’ll check… But I am guessing if I add a button to LaunchForm Part Entry from UD01 and then take Security Away to every other folder/sub-folder for myself besides the one where UD01 is it prob will say I dont have access because It couldnt find a single Match to Resolve to - Because the Folders (General Operations) are restricted, while the Menu ID within them is not.

(Calvin Krusen) #18

I’m not trying to be devils advocate (which I’m often accused of). I’m just trying to look for all possible shortfalls.

(Chris Conn) #19

I wonder if one could make use of this with a formname and customizationname:

public IStackableForm GetCachedForm(object session, string FormName, string CustomizationName, string ExtensionName, bool IsReadOnly)