Download presentation
Presentation is loading. Please wait.
Published byPriscilla George Modified over 9 years ago
1
#GPUGSummit | #INreno15 #GPUGSummit 25 DEVELOPMENT TRICKS AND HACKS IN 50 MINUTES David Musgrave MVP Managing Director, Winthrop Development Consultants Mariano Gomez MVP Senior Software Engineer, Mekorma
2
#GPUGSummit | #INreno15 Introductions What is this madness? 25 Tricks and Hacks – Dexterity – Visual Studio Tools Q & A 2 AGENDA
3
#GPUGSummit | #INreno15 Managing Director of Winthrop Development Consultants Microsoft Dynamics GP Most Valuable Professional (MVP) Worked with Microsoft for 13 and a half years Lives in Winthrop, a suburb in the city of Perth Where is Perth, Western Australia? 3 DAVID MUSGRAVE
4
#GPUGSummit | #INreno15
6
Senior Software Engineer at Mekorma Microsoft Dynamics GP Most Valuable Professional (MVP) Lives in Atlanta, Georgia, USA Born on a small Colombian island off the coast of Nicaragua Where is San Andres Island? 6 MARIANO GOMEZ
7
#GPUGSummit | #INreno15
9
Introductions What is this madness? 25 Tricks and Hacks – Dexterity – Visual Studio Tools Q & A 9 AGENDA
10
#GPUGSummit | #INreno15 Who has not worked with any of the tools? Who has worked with Modifier with VBA? Who has worked with Visual Studio Tools? Who has worked with Dexterity? Who has worked with Dexterity SBA or.Net Interop? Who has worked with more than one tool? Who has worked with more than one tool on a single project? 10 UNDERSTANDING THE AUDIENCE
11
#GPUGSummit | #INreno15 After the success of Mark Polino’s 50 tips in 50 minutes session at Convergence we thought we would try something similar We wanted to provide an overview of some tricks that will make your development life easier Also, we wanted to show some new techniques that you probably have not heard of before. 11 WHAT IS THIS MADNESS?
12
#GPUGSummit | #INreno15
13
DEXTERITY BEST PRACTICES
14
#GPUGSummit | #INreno15 Use a Binary sort order for your development and testing SQL Server environments – This will ensure that any code executed directly on SQL Server, such as Pass through SQL, Range where clauses and stored procedures will have the correct case for database, table and column names. – Avoids issues where supposedly working code starts failing at some customers when it works at other due to a Binary sort order. – While Binary is not as commonly used now, there are many legacy sites still using it. – Using Binary during development means that all code will work correctly for both Binary and DOCI. 14 1 OF 25: DEVELOP ON A BINARY SQL DATABASE
15
#GPUGSummit | #INreno15 Use a separate Dex.ini file for each project – Create a shortcut in the project folder to launch Dex.exe and pass the Dictionary file and Dex.ini file. Source Code Control provides version control – Tools such as Visual Source Safe and Team Foundation Server provide version control and can assist with multiple developers working on a single project. The generic text provide can still restore back to last version. Source Code Control must be used for upgrades – As resource IDs can change between versions, you can no longer use Dexterity Utilities Transfer >> Developer Update to upgrade between versions as this links using resource IDs when Source Code Control links using resource names. Using Developer Update can result in incorrect fields, datatypes, strings, etc. being used on a form. – Developer Update is still great for combining an extracted source dictionary back into a clean Dynamics.dic dictionary of the same version to create a development dictionary. 15 2 OF 25: USE SOURCE CODE CONTROL (SCC)
16
#GPUGSummit | #INreno15 Use of an Index File with Source Code Control is not optional – As Source Code Control uses Resource Names as the primary key and does not store Resource IDs, we must use an Index File to keep track of the Resource IDs assigned to resources. – Always use the Update… option from the Explorer >> Source Control menu and check use Index File. Never use the Update button on the Resource Explorer window as this does not use the Index File. – Always Update Index File when creating a new build for release to ensure any newly created resources are tracked. What happens if you don’t use an Index File – Chunk Files can get corrupted when extracting over the previous extract dictionary. – Security records, shortcuts & command navigation become corrupted as resource IDs have changed. 16 3 OF 25: USE AN INDEX FILE WITH SCC
17
#GPUGSummit | #INreno15 What is a _DUP Script? – A Dexterity event script on a form or window has two parts: The source code (with executable p- code) and a link to a focus event, such as Form Pre, Window Post or Field Change. – If you compile the code, but then fail to save the window or form, the script will exist in the dictionary, but the link will not have been saved. – When you attempt the add the script again, the script name has already been used and so a _DUP suffix will be added. Avoid _DUP Scripts with these simple steps – Immediately after creating a form or a window, close and save the window and click OK on the form. – Avoid discarding window changes or clicking cancel on forms after changes have been made to scripts. 17 4 OF 25: SAVE FORMS & WINDOWS TO AVOID _DUP
18
#GPUGSummit | #INreno15 Create Worksets to group logical sections of your project together – Worksets are a collection of shortcuts to resources of any type in the dictionary. Worksets can make finding resources much simpler. Using Worksets helps with memory – Having a workset for a project will help when revisiting old projects or new developers to a project. Create new resources while showing a workset – When new resources are created using the down arrow on the new button, they are automatically added to the current workset. Backup the ctree files used to store the Worksets – Make sure you backup the *ResExWsH.dat, *ResExWsH.idx, *ResExWsM.dat, *ResExWsM.idx files. 18 5 OF 25: USE DEXTERITY WORKSETS
19
#GPUGSummit | #INreno15 This is a little thing that can be very annoying – Please always add a blank line at the end of your scripts. Why? – Because it allows the mouse to select the last line of the script when highlight with a mouse. – It allows for a new line to be added easily to the end of the script. – It makes sure the syntax highlighting works as you are typing the script. – It’s like putting the toilet seat down at home, it makes it much nicer for the next person. 19 6 OF 25: FINISH A SCRIPT WITH A BLANK LINE
20
#GPUGSummit | #INreno15 It is best to always create scripts so they compile with no errors or warnings. – This makes it easy to see when an issue has been introduced. Handle Datatype mismatches – Either use the correct datatype to avoid overflow errors or use typing functions such as integer(), long(). – Avoid overflowing string datatypes, make sure they are long enough or use substring() to truncate. As a last resort, use Pragma precompiler commands – For developer only warnings, pass through Dexterity sanScript or SQL code, use: – pragma(disable warning LiteralStringUsed); pragma(enable warning LiteralStringUsed); – For unused parameters on function and procedure trigger handling scripts, use: – pragma(disable warning UnusedVariable); – For placeholder scripts used for triggering against, use: – pragma(disable warning NoExecutableCode); 20 7 OF 25: CREATE CODE WITH 0 ERRORS & 0 WARNINGS
21
#GPUGSummit | #INreno15 When creating your trigger registrations make sure that every trigger failure error message is unique. – Include identification that the trigger is from your product: : – A suggestion is to use the fully qualified name of the resource: of window of form – Include the trigger type and attach type: field focus before change Why? – It will make it simple for anyone to provide accurate information on exactly which trigger is causing issues, probably due to a parameter change on a script, or a change on a 3 rd party form. 21 8 OF 25: UNIQUE ERRORS WHEN REGISTERING TRIGGERS
22
#GPUGSummit | #INreno15 Make the bare minimum changes needed to move or add fields. – Never delete an original field as this is likely to break existing code. – Add whatever additional fields you need, use align tools to help get user interface layout correct. – Don’t forget to link prompts, link lookups and set the tab sequence. – No need to associate additional tables to the form. – Use Triggers to add scripts to form and include a check to see if alternate is in use to avoid illegal address errors. Why? – This approach is much easier to maintain, as you can identify where the scripts are without needing to check fields, run a script report, or find semicolons on the form. – If you need to recreate the alternate window between versions, it is simple and you will get compile errors if you missed adding a field. 22 9 OF 25: DON’T ADD SCRIPTS TO ALTERNATE WINDOWS
23
#GPUGSummit | #INreno15 CHECKING IF ALTERNATE FORM IS IN USE - PART 1
24
#GPUGSummit | #INreno15 CHECKING IF ALTERNATE FORM IS IN USE - PART 2
25
#GPUGSummit | #INreno15 CHECKING IF ALTERNATE FORM IS IN USE - PART 3
26
#GPUGSummit | #INreno15 Using Runtime_GetCurrentProductID() creates code that works in both test mode and runtime mode. – In Dexterity Test mode, the function will return 0 as you are developing in a copy of the Dynamics.dic dictionary. – In Runtime mode it will return the product ID of your product. – This is especially helpful when working with commands, command forms and menu navigation. When referencing your resources added by your product – Use Runtime_GetCurrentProductID(). When referencing existing resources in Dynamics.dic – Use the constant DYNAMICS, which has a value of 0. 26 10 OF 25: USE RUNTIME_GETCURRENTPRODUCTID()
27
#GPUGSummit | #INreno15 Well behaved ranges are inclusive ranges – Inclusive range: specify start record and end record and includes all records in between based on index – Inclusive ranges behave the same on all database platforms, so will work with Ctree and Memory tables Rules for a Well Behaved Range – In order of the segments/fields defined in the key/index: 1.Start and End segment must have 0 or more fields with the same value. 2.Start and End segment must have 0 or 1 field with different values (with Start less than End value) 3.Start and End segments must have the remaining values cleared/filled. 27 11 OF 25: USE WELL BEHAVED RANGES
28
#GPUGSummit | #INreno15 If you have a segment marked as descending in a key – All table actions involving that segment need to be treated in reverse. Range Setting – If using different values, then Start value must be greater than End value – If Clearing and Filling then Start value must be filled and End value cleared Moving through the table – If wanting to move in ascending order, need to use get last table and get prev table inside loop 28 12 OF 25: WORKING WITH DESCENDING KEY FIELDS
29
#GPUGSummit | #INreno15 Range Setting Requirements – Key fields for index in table buffer need to be set to start values when range start command issued. – Key fields for index in table buffer need to be set to end values when range end command issued. Traditional Method of Range Setting – Clear table, set start values, range start table, set end value, fill remaining end values, range end table Future Proof Range Setting – Clear table, set start values, range start table, fill table, set end values, range end table Why? – Only need to add code for fields getting set to specific values, the rest are automatically cleared/filled – If additional key segments are added to the index, no need to revisit code to fix range 29 13 OF 25: USE FUTURE PROOF RANGE SETTING
30
#GPUGSummit | #INreno15 FUTURE PROOF RANGE SETTING
31
#GPUGSummit | #INreno15 DEXTERITY ADVANCED TECHNIQUES
32
#GPUGSummit | #INreno15 Record a macro file while creating the chunk file – Start recording by closing Source, Editable and Destination Dictionaries – Record all steps including exiting Dexterity Utilities when finished – Edit the Macro file with Notepad.exe: Change Second line: Logging file nul Ensure Last line: MenuSelect title File entry Exit Launching the macro file – Create a shortcut to DexUtils.exe and pass the macro as a parameter; or – Create a batch file which runs DexUtils.exe and passes the macro as a parameter Why? – Using a macro ensures that all builds are created with same settings and steps, avoids human error – You can manually edit the macro to include additional alternate forms and reports, if needed – You can manually edit build numbers when creating a new build – You can find and replace folder paths & update version numbers when starting a new version 32 14 OF 25: AUTOMATE CHUNK FILE CREATION
33
#GPUGSummit | #INreno15 Use a Batch File to automate chunk file deployment – Copy chunk file from development folder to application folder – Launch Dynamics application in unchunk only mode using /CNKONLY Extend Batch File to create Dictionary Assemblies – Delete existing Dictionary Assembly *.xml and *.dll files – Run DAG.EXE (Dictionary Assembly Generator Tool) – Copy resulting Dictionary Assembly *.xml and *.dll files back to the development folder Signing and Code Signing (Digital Signature) – DAG.EXE can sign the dll files generate using the /S option and passing in a *.snk key file – Signing should be used to give the dll files a unique and constant GUID. Required for web client – SIGNTOOL.EXE can be used to Code Signing the dll files to add a Digital Signature – If shipping a product, Code Sign the dll files so they are trusted & don’t need to be unblocked 33 15 OF 25: AUTOMATE CHUNK FILE DEPLOYMENT
34
#GPUGSummit | #INreno15 BATCH FILE TO AUTOMATE CHUNK FILE DEPLOYMENT
35
#GPUGSummit | #INreno15 A quick check for triggers against Dynamics.dic – Just going into Test Mode by pressing Ctrl-T from the Dexterity Development environment will run the Startup script and its child scripts and validate that the triggers register without errors – Pressing Ctrl-T once the login window is displayed returns you to the Development environment Notes – Does not work for triggers against 3 rd party products as Test mode does not have 3 rd party dictionaries loaded – Does not work for triggers registered after login – Handy quick check after upgrading to a new version of Dynamics to see if parameters have changed 35 16 OF 25: TRIGGER REGISTRATION ERRORS QUICK TEST
36
#GPUGSummit | #INreno15 What is the Command Form? – The Command Form is a hidden form used as a container for a products navigation commands – It is opened when the application starts and remains open until the application is closed – To make the form hidden, the form contains a window with AutoOpen=False and Title=~internal~ Store data on the hidden window on Command form – Once the form is open, the windows exist even if they are not displayed to the user – Additional fields can be added to the hidden window and used to store data instead of global variables – Additional hidden windows can also be created if you want to “organize” the fields Why? – There is a limit to the memory that can be used as global variables, this method avoids hitting the limit – Faster than using memory tables or temporary tables to temporarily store data 36 17 OF 25: EXTRA USE FOR THE COMMAND FORM
37
#GPUGSummit | #INreno15 It is not always possible to stop Dexterity code – Reject script command only works for Focus event triggers running before the original – Sometimes it is just not possible to stop Dexterity code from running Using a pre and post trigger you can change behavior – The pre trigger can store a value into a global variable or hidden field on command form and replace the value with a custom value – The original code now runs with the custom value – The post trigger then restores the original value back from the global variable or hidden field Why? – Depending the original code, this method can be used to either prevent original code from working or make it work for you using your value rather than the original value – Re-uses existing code, can be much better than replacing the script and rejecting script – Allows other third party code triggering on the same location to still work 37 18 OF 25: THE TWO TRIGGER TECHNIQUE
38
#GPUGSummit | #INreno15 TWO TRIGGER TECHNIQUE
39
#GPUGSummit | #INreno15 Two common uses for the technique – Limiting a trigger on a commonly called script so that the trigger is only executed when you want it – Capturing data or table references in one location to be used in a second location based on timing Limiting execution of a Trigger to one location – Procedure A calls Function B, but Function B is used in many only locations. Want Trigger on Function B – Before Trigger on Procedure A sets global variable, After Trigger on Procedure A clears global variable – Trigger on Function B checks status of global variable and aborts if not set to true Capturing Data or Table Reference – Procedure A calls Procedure B which passes temporary table buffer, then it populates the table, then calls Procedure C, then processes table contents. Want to modify table contents before it is processed. – Before Trigger on Procedure B to capture table buffer reference can store it as a global variable – Trigger on Procedure C then uses table('Table Reference' of globals) to update table contents – After Trigger on Procedure A clears table reference global variable as it is no longer valid 39 19 OF 25: THE THREE TRIGGER TECHNIQUE
40
#GPUGSummit | #INreno15 THREE TRIGGER TECHNIQUE – TYPE 1
41
#GPUGSummit | #INreno15 THREE TRIGGER TECHNIQUE – TYPE 2
42
#GPUGSummit | #INreno15 Changing Context of Triggers using default command – Normally a trigger procedure runs in the same context as a global procedure. – Use default form to command to change context to form level (same as FORM_PRE or FORM_POST) – Use default window to command to change context to specific window on a form Why? – This can make coding of scripts much simpler as there is no need to fully qualify the window and form – By changing context, you can access the form’s table buffers, including scrolling window or temp tables Notes – As scripts are now running in the context of the form, you cannot reference tables that are not associated with the form. – To reference other tables, use global functions to perform any actions on other tables as needed. 42 20 OF 25: USING DEFAULT FORM / WINDOW TO
43
#GPUGSummit | #INreno15 DEFAULT FORM / WINDOW EXAMPLE
44
#GPUGSummit | #INreno15 Using Dexterity precompiler directives – Dexterity supports conditional compilation using #if, #elseif, #else and #end precompiler directives – Work with Constants defined in the dictionary, such as WDC_PROD_MAJ or DEBUG Why? – You can use conditional compilation to maintain a single code base for a product for all current versions of Microsoft Dynamics GP while still supporting new features. Conditional Compilation prevents compilation errors for missing resources, scripts or new sanScript commands and functions – You can use conditional compilation based on a DEBUG constant to create “Debug” builds with additional messages which can be disabled by changing the constant to false before final builds Notes – The Hash (#) must be the first character on the line to be identified as a pre-compiler directive – The lines are not terminated with a semicolon (;) 44 21 OF 25: USE CONDITIONAL COMPILATION
45
#GPUGSummit | #INreno15 CONDITIONAL COMPILATION EXAMPLE
46
#GPUGSummit | #INreno15 Passthrough SQL commands must be formed correctly – This includes commands executed by SQL_Execute(), where clauses used with range table where as well as parameters passed to stored procedures Strings and Maximum Character (missing Z issue) – Use SQL_FormatStrings( ) to add single quotes and double up any single quotes to avoid injection – Use system 9600 command to obtain maximum character for SQL sort order. Fill gives char(255) = ÿ Date and Time Issues – To avoid issues with date and time formats (both regional and user format) don’t use str() function – Use SQL_FormatStrings(sqlDate( )) for Dates, this uses format 'YYYYMMDD' – Use SQL_FormatStrings(sqlTime( )) for Times, this uses 24hr format 'HH:MM:SS' More Information – http://blogs.msdn.com/b/developingfordynamicsgp/archive/2013/11/04/quick-tip-unusual- behaviour-when-working-with-sql-server-from-dexterity.aspx http://blogs.msdn.com/b/developingfordynamicsgp/archive/2013/11/04/quick-tip-unusual- behaviour-when-working-with-sql-server-from-dexterity.aspx 46 22 OF 25: AVOID ISSUES WITH PASSTHROUGH SQL
47
#GPUGSummit | #INreno15 DEXTERITY WORKAROUND TECHNIQUE
48
#GPUGSummit | #INreno15 Version 12.0 of Dexterity changed form export format – This affects how pictures are associated with local push button fields in forms – Backward compatible: Versions 12.0 or later can import previous format without issues – However, version 11.0 or earlier will lose images from local pushbutton fields if importing new format If working with a shared code base across versions – Suggest to always develop new code in v11.0 or earlier and export and import into v12.0 or later How to fix exported form file to allow import – If you need to take an exported form back from v12.0 to v11.0, you can fix it with Notepad.exe – Find StaticType"Picture" Replace with StaticType"Mixed" but only for Control "PushButton" Notes – Navigation commands defined on forms have additional options for v12.0 which can be lost if importing from v11.0, it is best to just remake changes for each version for command forms – Global procedures on v14.0 can have SBA Metadata which will be lost if importing from v11.0 48 23 OF 25: ISSUE WHEN IMPORTING EXPORTED FORMS
49
#GPUGSummit | #INreno15 V11.0 OR EARLIER LOCAL FIELD FORMAT
50
#GPUGSummit | #INreno15 V12.0 OR LATER LOCAL FIELD FORMAT
51
#GPUGSummit | #INreno15 DEXTERITY VERY ADVANCED TECHNIQUE
52
#GPUGSummit | #INreno15 What is the old() issue? – It is very common when writing custom code to need to change a field’s value – Usual method is to set field to the new value and use run script to execute the change script – old() does not work when using set field, run script field, it returns the same as the current value – Hence no change is detected and diff() returns 0. This means that the code fails to work correctly – For example: Item allocations are not shifted between sites when changing the transaction location The problem is focus – For old() to work, the field must have focus with the old value before the value is changed – Using the focus command does not actually take effect until all foreground scripts have completed – Dexterity Help says: This function should not be used in a change script run using the run script or run script delayed statements. Focus must be in the field for which this function is run for it to operate properly. 52 24 OF 25: SOLVING THE OLD() ISSUE – METHOD 2 PT.1
53
#GPUGSummit | #INreno15 Solving the old() issue, this is better second method – Leverages functionality of open form return to command and return command – When field is “returned”, the focus is placed on the field, the field is changed, then focus moves to next field in the tab sequence which causes the change script to run How it works – Create WDC_Return form with hidden Dummy window. On the hidden window have a local field of each data type and a Return Pushbutton. Scripts then open form and return to the desired field Notes – Cannot use,nofocus option as that stops old() from working – Must use push button with run script to issue the return command – Cannot be used on last field in scrolling window as the tab off the field forces the scrolling window to a new line, if necessary adjust tab sequence on modified window to workaround. 53 24 OF 25: SOLVING THE OLD() ISSUE – METHOD 2 PT.2
54
#GPUGSummit | #INreno15 SOLVING THE OLD() ISSUE EXAMPLE
55
#GPUGSummit | #INreno15 SOLVING THE OLD() ISSUE CODE – PART 1
56
#GPUGSummit | #INreno15 SOLVING THE OLD() ISSUE CODE – PART 2
57
#GPUGSummit | #INreno15 SOLVING THE OLD() ISSUE CODE – PART 3
58
#GPUGSummit | #INreno15 SOLVING THE OLD() ISSUE CODE – PART 4
59
#GPUGSummit | #INreno15 VISUAL STUDIO TOOLS
60
#GPUGSummit | #INreno15 Visual Studio Tools addons without WinForms – A Visual Studio Tools addon that does not have any WinForms, but only uses original or modified Dexterity forms should be able to work on the Web Client without much additional work DLL files must be signed – Both Dictionary Assembly and Addon dll files must be signed to work on the web client Supported Platform must be enabled – The SupportedDexPlatforms property must be set for both DesktopClient (default) and WebClient – Commands are similar but slightly different for C# and Visual Basic.Net, added above class GPAddIn 60 25 OF 25: USING ADDONS WITH THE WEB CLIENT
61
#GPUGSummit | #INreno15 ENABLING ADDON FOR WEB CLIENT
62
#GPUGSummit | #INreno15 SERVICE BASED ARCHITECTURE
63
#GPUGSummit | #INreno15 Form ServiceCodeGenerator – Hidden form in the Dynamics.dic dictionary Create.Net Objects – Create a.Net Object script template from table definitions Map Fields from Object to window fields – Creates the scripts to be used for a window wrapped service Set Object from Table – Creates the scripts to be populate the object variable from a table record 63 26 OF 25: BONUS TIP: SERVICE CODE GENERATOR
64
#GPUGSummit | #INreno15 64
65
#GPUGSummit | #INreno15 ALMOST DONE
66
#GPUGSummit | #INreno15 If you liked this session and want more – Make sure you say so in your conference evaluation and feedback We have more tricks and hacks – While preparing for this session, we created over 60 tricks and hacks – It was difficult to select the first 25 to include in this session Do you have any cool tricks and hacks? – If you have something cool you have worked out, please let us know and we might include it in future sessions and give you credit 66 27 OF 25: WANT MORE, JUST ASK
67
#GPUGSummit | #INreno15
68
David Musgrave’s Winthrop Development Consultants Blog http://www.winthropdc.com/blog The Dynamics GP Blogster blog (by Mariano Gomez) http://dynamicsgpblogster.blogspot.com/ Developing for Microsoft Dynamics GP Blog – retired (by David Musgrave & the Developer Support Team) http://blogs.msdn.com/DevelopingForDynamicsGP/http://blogs.msdn.com/DevelopingForDynamicsGP/ or http://aka.ms/Dev4DynGPhttp://aka.ms/Dev4DynGP 68 LINKS
69
#GPUGSummit | #INreno15
70
QUESTIONS? Contact: david@winthropdc.com & mariano@mekorma.comdavid@winthropdc.commariano@mekorma.com
71
#GPUGSummit | #INreno15 Main Topic 1: Size 22pt – Subtopic: Size 20 pt Main Topic 2: Size 22pt – Subtopic: Size 20 pt Main Topic 3: Size 22pt – Subtopic: Size 20 pt 71 HEADER TEXT: SIZE 30PT
72
SECTION TITLE
73
QUESTIONS? Contact: xxxx@xxxx.com
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.