• Microsoft Dynamics NAV Team Blog

    The asymmetric stream

    • 0 Comments

    Since NAV’s Stream introduction, there has been confusion about when to use READ and when to use READTEXT; when to use WRITE and when WRITEXT.

    As it is documented, InStream.READ  and OutStream.WRITE are meant to be in binary format, which means that Text strings will be ‘zero terminated’ when written, and a ‘zero terminated’ is expected when you are using READ; however READTEXT will not expect a ‘zero terminated’ text, but can accept one.

    This very last feature makes the streams asymmetric, as you can write different binary formats than what you can read.

    Take the following code snippet:

    Streams code

    If we examine the file that gets created (in a binary text editor), you will notice that the Texts are in fact ‘zero terminated’, but the READTEXT will be able to read them individually.

    Now, this is where the fun begins. We can change the READTEXT to be READ (as it should have been) and everything will continue to work exactly the same…, almost. You will notice that the readCount now (when using InS.READ) will include the zero termination, whereas before the count was only for the characters in the text. Actually, if you put a return value in the WRITE (char 13), you will notice that the zero termination is included in the count (because actually that was the binary format of the Text).

    So, count in count := OutS.WRITE('My text.'); will be 9 (8 characters and a zero termination), whereas count := OutS.WRITETEXT('My text.'); will be 8. The reason why it was decided to return the written bytes, was precisely so that people would know how many bytes are sent through the Stream.

    Another thing to take in consideration when working with Streams are CODE types. When writing CODE types using OutStream.Write, they are NOT written in NAV binary format. So they are not symmetric with the FILE.WRITE function; however, InStream.READ(CodeType) will accept either data written using OutStream.WRITE(CodeType), or FILE.WRITE(CodeType).

    Another possibility is to write data using OutStream.WRITETEXT(Text) and read it via InStream.READ(Text). Just take in consideration that when using OutStream.WRITE(Text), the Text will be zero terminated and when using OutStream.WRITETEXT(Text), it will not. 

    Jorge Alberto Torres (jtorres)
    Software Developer Engineer

  • Microsoft Dynamics NAV Team Blog

    Simple query to check the recent performance history II - now including Query Plan information

    • 0 Comments

    One of the queries I use the most, is the pplan-cache query from this post:

    Simple query to check the recent performance history

    The good thing about the query is that it shows information that could otherwise require a lot of work (collecting and analysing traces files). And the query does not need any advance work or setup. It can just be run. So it's a very easy way to receive information from a system, which is often very useful as a first step in troubleshooting performance. For more details about the result of the query, refer to the post linked above.

    Below is a slightly enhanced version of the query. Since the query is based on the cache of compiled query plans, it is not a big step to extend it to also include the query plan itself, and even extract certain information from the plan if you know what you are looking for.

    So this query does the same as the original one, but with the following additions:

    • New column query_plan is included. It shows the query plan as xml which may be difficult to read, but it contains the full plan. Note: Some times, for no apparent reason, the query plan can't be retrieved, so it may not show the query plan on all lines.
    • cursor_type, just as an example of how to retrieve data from the query plan. If you find other things in the plans that may be interesting, then use the syntax to retrieve this further information.

    Here is the updated query

    SELECT TOP 100

    SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,

    ((CASE statement_end_offset

    WHEN -1 THEN DATALENGTH(st.text)

    ELSE qs.statement_end_offset END

    - qs.statement_start_offset)/2) + 1) as statement_text,

    execution_count,

    case

    when execution_count = 0 then null

    else total_logical_reads/execution_count

    end as avg_logical_reads,

    last_logical_reads,

    min_logical_reads,

    max_logical_reads,

    plan_handle,

    ph.query_plan,

    -- Query Plan Information

    case when

    ph.query_plan.exist('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtCursor/ns:CursorPlan/@CursorRequestedType)[1]') = 0

    then '' else

    ph.query_plan.value('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtCursor/ns:CursorPlan/@CursorRequestedType)[1]','nvarchar (max)')

    end as cursor_type

    FROM sys.dm_exec_query_stats as qs

    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as st

    CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) as ph

    ORDER BY max_logical_reads DESC

    :

     

    What I would really like, is to receive feedback on what parts of the query plans are useful. Then extend the query even further to include as much useful information as possible. For exdample, in some cases the query plan contains missing index-information. The lines below can be copied into the query above to include this information. Any feedback on whether this is useful or not, and whether other information from the query plans can be useful is really very welcome. You can add comments about this below.

    -- Missing Indexes

    ,case when ph.query_plan.exist('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup)[1]') = 0

    then ''

    else ph.query_plan.value('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup/@Impact)[1]','nvarchar (max)')

    end as missing_index_impact,

     

    case when ph.query_plan.exist('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup/ns:MissingIndex/@Table)[1]') = 0

    then ''

    else ph.query_plan.value('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup/ns:MissingIndex/@Table)[1]','nvarchar(max)')

    end as missing_index_table,

    case when ph.query_plan.exist('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup/ns:MissingIndex/ns:ColumnGroup/ns:Column/@Name)[1]') = 0

    then ''

    else ph.query_plan.value('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";(/ns:ShowPlanXML/ns:BatchSequence/ns:Batch/ns:Statements/ns:StmtSimple/ns:QueryPlan/ns:MissingIndexes/ns:MissingIndexGroup/ns:MissingIndex/ns:ColumnGroup/ns:Column/@Name)[1]','nvarchar(max)')

    end as missing_index_field

     

    Lars Lohndorf-Larsen (Lohndorf)
    Escalation Engineer

  • Microsoft Dynamics NAV Team Blog

    Debugging in NAV 2009

    • 3 Comments

    UPDATE 25 August 2010! You cannot use the Express version of Visual Studio 2008 SP1 to debug Microsoft Dynamics NAV 2009. However, a useful and free visual debugger with slightly limited functionality - DbgClr.exe - can be downloaded as part of the .NET Framework 2.0 SDK: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec

    --- 

    UPDATE 18 December 2009! The most up-to-date version of this content is available in the Microsoft Dynamics NAV 2009 Developer and IT Pro Help on MSDN: http://msdn.microsoft.com/en-us/library/dd301071.aspx.

    ---

     
    UPDATE!!! Debugging is not available in the Marketing Beta, so if you have access to a later build you can try this out. If not you will have to wait for RTM.
    Also note that SP1 for either Visual Studio 2005 or Visual Studio 2008 is required.
    ---

    In this post I will give you a example on how to debug in NAV 2009.

    1. EnableDebugging in CustomSettings.config found here: C:\Program Files\Microsoft Dynamics NAV\60\Service

    image

    2. Now Restart the “Microsoft Dynamics NAV Server” service

    image

    3. Now we have debugging enabled. Now start the RoleTailored client. This will take a bit longer to start up, because C# files are generated for each of the objects. (Pages, Codeunits, Reports etc.)

    4. Now we need to find a place to debug. In this example I will make a codeunit with a simple message and add this to an action on the Customer list.

    5. Create a Codeunit. Ex. 50000

    6. OnRun trigger place the following code: MESSAGE ('Debug test')

    image

    7. Save and compile Codeunit 50000.

    8. Now let us add this codeunit to a action. Design page 22 and navigate to the Actions on page 22.

    9. Insert a new action below the the Customer Action group

    image

    10. Hit F9 and enter this code on the Debug test -  OnAction trigger: CODEUNIT.RUN(50000);

    image

    11. Save and compile page 22

    12. OK we now have all code completed so now let us set a breakpoint in Visual Studio.

    13. Navigate to “C:\ProgramData\Microsoft\Microsoft Dynamics NAV\60\Server\MicrosoftDynamicsNavServer\source\Codeunit”

    14. Assuming that you have Visual Studio installed, (In my case I’m using Visual Studio 2008 with SP1) open Codeunit50000.cs

    image

    15. If you have UAC turned you will need to open Visual Studio with “Run as administrator”.

    16. Now we need to attach the NAV service. Select “Debug / Attach to process…”

    17. Attach Microsoft.Dynamics.Nav.Server.exe

    image

    18. Your screen should now look like this:

    image

    19. Now add a break point on the message “Debug test”

    image

    20, With this done now let us go to RoleTailored client.

    21. Navigate to Customer List and see that you have a new action called “Debug test” under “Related Information”

    image

    22. Now select “Debug test”

    23. Visual Studio will come back in focus with the breakpoint selected.

    image

     

     

     

     

     

     

     

     

     

     

     

    24. Now try to hit F5 and debugging will continue and RoleTailored client will come back in focus and show the message “Debug test”:

    image

    Thanks,

    Claus Lundstrøm, Program Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    Action and Activity Button icons in Microsoft Dynamics NAV 2009

    • 0 Comments

    Update!!! Please find an updated list of icons available here:

    Regards,
    Claus

    ******

    First, if you have not downloaded the just released Marketing Beta for Dynamics NAV 2009, this can be downloaded from here. Requires access to Partner Source.

    In the Marketing Beta for Dynamics NAV 2009 you will find new walkthroughs for how to create Pages for the new RoleTailored client.

    But one thing that you can not find in the “nav_adg.chm", are what icons you can use in the RoleTailored client, because this topic will be added later.

    So to save you the time reverse engineering the Demo Database to create this list, if you are to create a new page, let me share these icons with you.

    But first let me give you an example on a Action and an Activity Button. If you already are familiar with this, you can skip to the end of this blog, where all the icons are listed.

    Example of an Action in Page Designer:

    1. Open Object Designer

    2. Navigate to the new Page object

    3. Design page 22, Customer List

    4. Navigate to the bottom of the page to access the Page Object itself

    5. Right click and select “Actions”, you view should now look like this:

    image

    6. You are now looking at the Action Designer which is captured inside the Page Designer.

    7. Scroll down to <Action58>, Bank Accounts and select properties on this action. Your view should now look like this:

    image

    8. The most important property here is the “RunObject”, which tells which object are activated, when this Bank Accounts action is clicked, but for this blog I’m concentrate on the “Image” property so I will not go into more detail for the “RunObject”. Notice that the Image property is undefined. So how will this action actually look in the RoleTailored client if no image is associated to this action? Let us promote this action and see.

    9. Set “Promoted” to Yes

    10. Set “PromotedIsBig” to Yes

    11. Save and compile page 22.

    12. Open RoleTailored client.

    13. Navigate to the Customer List, if you have the Customer List open already, just refresh the list by clicking“Refresh” in the top right corner. You will now see your “Bank Accounts” action promoted with the default icon used. The default icon will be used when the Image property has not been set:

    image

    14. Now let set the “Image” property on the “Bank Accounts” action. Go back to the Action Design for Page 22 and select the properties for the “Bank Accounts” action.

    15. Set the “Image” property to “BankAccountStatement”

    16. Save and compile page 22.

    17. Refresh Customer List in RoleTailored client and your icon for “Bank Accounts” action will now look this.

    image

    Now let us look at an example of an Activity Button in Page Designer:

    1. Activity Buttons belongs to the RoleCenter so to create or modify an Activity Button we need to be designing a Page of PageType “Rolecenter”. So let us look at page 9006.

    2. Design page 22

    3. As for the Actions the Activity Buttons are also found in the Action Designer, so Navigate to the bottom of the page to access the Page Object itself.

    4. Right click and select “Actions”, you view should now look like this:

    image

    5. Instead of modifying an existing Activity Button as we did for the Action above, let us create a new one.

    6. Navigate to the ActionContainer ActivityButtons area of the Action Designer:

    image  

     

    7. Role Center 9006 has one Activity Button called “Posted Documents”. Let us create a new Activity Button call “Bank” just above “Posted Documents”. Place your cursor on “ActionGroup” “Posted Documents” and press F3.

    8. A new line is created. Set “Caption” to “Bank” and “Type” to “ActionGroup”

    9. Open properties and set “Image” property to “Bank”.

    10. Make sure that the 2 ActionGroups “Bank” and “Posted Documents” are at the same indention level. You might need to move “Bank” to the right to align with “Posted Documents”.

    11. We could stop now and see the Activity Button in RoleTailored client, but let us add an action to this new Activity Button, so we actually have something happening when you click the Activity Button “Bank” in the RoleTailored client.

    12. Create new line bellow, the “Bank” “ActionGroup”, and set “Caption” to “Bank Accounts” and “Type” to “Action”. Make sure that this action is indented one level in from the ActionGroup  above.

    13. Open properties for “Bank Accounts” and set “RunObject” to “P371” (Page Bank Account List)

    14. Now restart RoleTailored client to see your new Activity button. Note: Refresh does not work in Activity Button area of the Role Center, so you will need to restart the RoleTailored client to see your “Bank” Activity Button. Hopefully this we be solved in a future build, so you don’t need to restart to see your changes made in Page Designer. :-). After the restart you RoleTailored client should now look like this:

    image

    So now you have seen how to set the “Image” property on an Action and an Activity Button, let us see the icons you can use.

    Icons which can be used for Actions:

    Removed please use online help: http://msdn.microsoft.com/en-us/library/dd568728.aspx

    Icons which can be used for Activity Buttons:

    Removed please use online help: http://msdn.microsoft.com/en-us/library/dd568709.aspx

    Thanks,

    Claus Lundstrøm, Program Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    List of released updates for SQL Server 2005 SP2

    • 0 Comments

    The link below lists build numbers, KB numbers and links to cumulative updates updates 1 to 9 for SQL Server 2005: 

    List of build numbers and cumulative updates 1-9 for SQL Server 2005

     

     Also see this post for relevance of SQL Updates to Microsoft Dynamics NAV:

    Overview of updates for SQL Server 2005 SP2

     

    Lars Lohndorf-Larsen

    Microsoft Dynamics UK


    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    Microsoft Dynamics NAV 5.0 Documentation Source Files Available to Partners

    • 4 Comments

    Earlier this year, Michelle, my colleague on the Microsoft Dynamics NAV documentation team, wrote a blog post about improvements that we have made to the content for Microsoft Dynamics NAV 2009. In addition to improving the product documentation, we are also working to improve how partners can customize and extend the Help.

    In April, we published all of the Microsoft Dynamics NAV 5.0 platform documentation to the Microsoft.com Download Center. And now, we are releasing all of the source files for Microsoft Dynamics NAV 5.0 application Help on PartnerSource (log-in required). When Microsoft Dynamics NAV 2009 is released, we’ll also provide the new application Help source files on the same schedule as the localized releases.

    Providing our partners with the documentation source files is only a first step toward improving Help customization. Feedback that we have heard is that the Online Help Guide (available on PartnerSource) is daunting. For Microsoft Dynamics NAV 2009, we will be replacing this guide with a streamlined version focused on what you need to do to customize and build documentation for your Microsoft Dynamics NAV solution or add-on.

    We are also updating GATE for Microsoft Dynamics NAV 2009. While the functionality will be very similar to what you are using today, we’ll be making GATE more robust and easier to use by rewriting it as a .NET application.

    Given the amount of time that we have left in this product cycle, these tactical changes are what we can provide in the Microsoft Dynamics NAV 2009 timeframe. You can continue to use RoboHelp (or your favorite HTML or Help authoring tool) to create Help. Over the coming months we will be developing our post-Microsoft Dynamics NAV 2009 strategy for improving Help customization. Based on what we heard at Convergence in March and in one-on-one discussions with several partners, we will be focusing on the following themes:

    • Developing an easy mechanism to create and edit documentation, for example, Microsoft Word.
    • Providing more procedural content which you can customize for your solution or add-on.
    • Enabling you to create Help for objects.

    We’d like to continue to hear what your needs are, so we can ensure that we are improving the process for customizing and extending Help. You can add your comments below or e-mail us at navhelp@microsoft.com. Here are some questions to get you started:

    • How do you use the content that we provide?
    • What types of Help do you provide to your customers to assist them in using your solution?
    • If you don’t provide your customers with customized Help, what are the main reasons for not doing this? How does this impact your support costs?
    • How will you use the source files for all of our Help, in all available languages? Will you customize these CHMs? Repackage Help into another format? Or do something else?
    • Do you extend Help with information about the changes that you have made to Microsoft Dynamics NAV, such as new tables, forms, pages, etc.? How important is it to be able to extend Help? What would make this scenario more efficient for you?
    • Have you used the Online Help Guide toolkit? How well did it help you accomplish Help customization?
    • Do you know that we removed Company Notes in Microsoft Dynamics NAV 5.0 and why? Were you using Company Notes? What worked for you about this solution? What didn’t work?
    • If you customize the content that we provide, how do you determine what has changed from version to version?

    It’s important for us to ensure that we are providing an efficient way for you to customize the documentation. We’re looking for volunteers to test our new Help processes, and provide us with feedback on how well these solutions meet your needs. In return, we’ll offer extra assistance in using these processes. If you would like to participate, please e-mail navhelp@microsoft.com.

    - Paul Chapman

  • Microsoft Dynamics NAV Team Blog

    New Drop Down window in Microsoft NAV 2009 using Fields Groups

    • 4 Comments

    I have now been asked many times how the new Drop Down window in Microsoft NAV 2009 is defined, so let me give you an example on how this works.

    In this screen dump, I have just clicked the Drop Down arrow on the field ”Bill-to Customer No”, on the Customer Card, and our new Drop Down window appears displaying the columns No., Name, City, Post Code, Phone No. and Contact.

    image

    So how do I define that when I click “Bill-to Customer No.” it displays a Drop Down? And how are the columns defined which are displayed in the Drop Down?

    Let us look at a field which actually shows a List page and change this field to show a Drop Down. This could be ex. “Post Code” also found on the Customer Card.

    Let us see what happens when I click “Post Code”:

    image

    So in standard NAV 2009 we show a List page where the use can select from the available Code and Cities found in the demo database. I would like to change this into a Drop Down so let us go into the Object Designer and explorer why I shown a List page when clicking the Post Code field.

    My first thought is to look at Page 21 in the Page Designer and look at the properties for “Post Code”:

    image

    But since nothing is specified on the “Lookup” property this must be on table level. In table 18 you find the following code  “PostCode.LookUpPostCode(City,"Post Code",TRUE);

    image

    With this on the OnLookup trigger we will show a List page and not a Drop Down, so let us delete what is on the OnLokup trigger and see how the “Post Code” fields now behaves in the RoleTailered client:

    image

    So now I got my Drop Down on “Post Code” but I actually want to sort the columns different and add other columns to the Drop Down. To do this I used a new thing we call “Fields Groups”.

    Since when I look at the “Post Code” on the customer card we actually lookup in Post Code table 225, so to change the columns displayed we need to look at this table, so back to Object Designer and design table 225.

    In design mode click “View” and notice a new field called “Field Groups”. Notice that this is blank, so the “Code” and “City”  which are displayed in Drop Down above are shown because these fields are Primary Keys specified on the Table.

    image

    Now let us define the columns shown in the Drop Down window of “Post Code”.

    In the Name type “DropDown” and in group select the assist button and select City, Code and City Search:

    image

    Your Field Group should now look like this:

    image 

     

     

     

     

     

     

    Now compile table 225 and go back to your Customer Card. If you had one open already you will need to reopen since we have changed the underlying data.

    Your Drop Down now displays like this:

    image 

    We have now completed created our new Drop Down window, but before I end this blog I would to like show you a bit more what you can do with this Drop Down.

    I have been been in the NAV group for almost 10 years now so I’m a keyboard shortcut addict so let me show a small tip.

    While standing on the “Post Code” field press “ALT+ARROW DOWN”, Drop Down will show up.

    Now type “New”. The Drop Down will now be sorted on all cities starting with “New”:

    image

    You might have noticed that “City” is bold in the Drop Down. This signals that the Drop Down will be searched based on upon the field “City”. So in this case when we type “New” we will see the Cities which start with “New”

    Now let us make “Code” the default.

    Press “ARROWDOWN” to get down into to Drop Down.

    Press “ARROWRIGHT” to get to the “Code” column. Notice that “Code” now becomes bold, and if you are still searching on “New” the list will become blank:

    image

     

    Now type “US“ and your Drop Down window will now be sorted on all codes which is starting with “US“:

    image

    Also notice that “Code” going forward will be column to sort on as this information is stored in the Personalization store.

    So here you have it, my first blog ever.

    Thanks,

    Claus Lundstrøm, Program Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 - Where is the zup file?

    • 0 Comments

    In previous versions, all local client settings are stored in the .zup file. In Microsoft Dynamics NAV 2009, this is a bit more complex. This post tries to describe which settings are stored where.

    In addition to that, with NAV 2009 you may be spending a lot of time looking for files with long folder-names. So this post also shows you the location of each file, to make it quicker to find them.

     

    /// Blog updated October 2nd: Section "temporary server files" updated with path for Windows Server 2003.

    Setup files and tables in NAV 2009

    In NAV 2009, settings are stored in various places. The following lists what is stored where. some settings are stored in files, and some in tables. I hope I have included everything here. But if the list should be incomplete, I would appreciate comments at the end of this post.

     

    Client side:


    PersonalizationStore.xml
    stored in:
    %AppData%\Microsoft\Microsoft Dynamics NAV\

    This file stores some personal settings for the client like resizing of columns. It is probably the closest thing to the old zup file there is. The data in this file is primarily binary because it it not supposed to be updated manually. Even if you could edit the file (if you could find the settings you wanted to edit), then this is unsupported. But, like the old zup file, you can delete or rename it, and next time the client opens, it will create a new one.

    ClientUserSettings.Config
    Stored in:
    %ProgramData%\Microsoft\Microsoft Dynamics NAV\

    This file is where you can set RTC to connect to a specific service tier and/or a specific port.

    Server side:

    CustomSettings.config
    stored in (default):
    C:\Program Files\Microsoft Dynamics NAV\60\Service\
    This is where you set up parameters for the Service Tier like SQL Server name, Database name, port number etc.

    temporary Server files
    Stored in:
    %ProgramData%\Microsoft\Microsoft Dynamics NAV\60\Server

    /// Update

    The path above is for a Vista OS. If you run NAV server on Windows Server 2003, the path is:

    C:\Documents and Settings\All Users\Application Data\Microsoft\Microsoft Dynamics NAV\60\Server\

    /// -----

    The service tier uses this folder for various temporary files. It is definitely not recommended to change any files here! But it might be a place for troubleshooting certain problems (though I am not sure what kind of problems).

    Tables:


    2000000075 - "User Metadata"
    When you go to "Customize this page", then it's stored here.If for example a user ads new parts, like a chart or does anythign else herel,this table contains one record for each urse, for ach pae that they have persinalised.

    2000000071 - "Object Metadata"
    This table stores all the objects for RTC. Whenever you compile an object, it transforms it to a format that is designed for RTC and stores it in this table. You can delete entries here, though I would not recommend it. But if you do, and want it back, then compile the missing object from Object Designer. The data in this table is generally binary, so also not something to modify and definitely not necessarily supported or documented.

     

    Lars Lohndorf-Larsen (Lohndorf )
    Microsoft Dynamics UK
    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    Session Monitor for SQL Server 2005

    • 0 Comments

    Session Monitor is not a new tool, but it did stop working with SQL Server 2005. So I think that a lot of people stopped using it, which is a shame. The things that were broken now work again, and I would recommend anyone with any kind of blocking problems to implement this tool. With this post I hope to get some people to use it again, and to provide a new tool to anyone who did not know it exists.

    Purpose of the tool

    The purpose of the Session Monitor tool is to show a live picture of any current blocks in the Microsoft Dynamics NAV database. And to show it in a familiar environment, i.e. a NAV form. It is an extension of the information you get when going to File -> Database -> Information, and drill down on Sessions.

    What the tool does:

    • Shows live information about who is blocked by whom
    • Shows which user is at the top of a blocking chain
    • Shows if a user is involved in blocking, i.e. either being blocked or is blocking someone. So you can filter out all sessions that are not involved in blocking
    • Shows the wait resource, i.e. on which table the block is

    This is how the Session Monitor shows a blocking situation:

    SessionMonitor

    As default it refreshes every second.

    Some of the useful features of Session Monitor are:

    • Filter on "Involved in Blocking". Then, as soon as there is a block it will show up. This is especially useful when you have more sessions that can fit on the screen, which means that there might otherwise be a block outside of the form.
    • Wait Resource tells you on which table the block is, which helps you get some idea about in which area of the application it is.
    • Originating blocker ID shows the head-blocker. This is useful when a user is blocked by someone who is blocked by someone else, etc.
    • Wait Time shows how long the block has been there.

    How to get it to work

    As mentioned, the tool stopped working in SQL Server 2005. But there are corrections for this now. First, download the tool, which is part of the "Performance Troubleshooting Guide", available for download here (PartnerSource login required):

    Microsoft Navision SQL Resource Kit

    The original tool contains a SQL query (Session Monitor (SQL Server).sql) which is the part that doesn't work for SQL Server 2005. So don't run this query.  Run the query from this KB article instead (PartnerSource login required here too):

    KB 933042 - Error message when you use the Session Monitor feature in Microsoft Dynamics NAV: "Invalid length parameter passed to the substring function"

    Note!: Run the query on the NAV database - not on Master, or any other database you have on SQL Server.

    In NAV, import the object "Session Monitor (SQL Server).fob" from the Performance Troubleshooting guide.

    Make one change - otherwise in some cases it will fail with an INSERT error:

    Design codeunit 150011 "Session Monitor Mgt. (SQL Srv)", and replace this line:

    RefreshUserActivity()
    SELECTLATESTVERSION;
    IF Session.FIND('-') THEN
      REPEAT
        SessionTmp := Session;
        // SessionTmp.INSERT; Remove this line and replace with:

        IF SessionTmp.INSERT THEN ; // New line  
      UNTIL Session.NEXT = 0;

    Those are the changes needed to get it to run on SQL Server 2005,

    Lars Lohndorf-Larsen (Lohndorf)
    Escalation Engineer

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 - New one-stop Launch Portal on PartnerSource

    • 0 Comments

    One stop Microsoft Dynamics NAV 2009 launch portal for partners can be found at this link on PartnerSource (login required):

    Launch Portal for Microsoft Dynamics NAV 2009

    Follow the portal for:

    • Key Announcements
    • What's New
    • Readiness and Training
    • Sales and Marketing Materials
    • Events
    • Coming Soon

     

    Lars Lohndorf-Larsen

    Microsoft Dynamics UK

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 - How to generate charts / KPIs

    • 5 Comments

    Microsoft Dynamics NAV 2009 has a new graphical object type called Charts or KPIs (Key Performance indicators). It is a way to create simple graphical charts, to give a visual overview of key figures. This post describes what you can and cannot do with charts, and it contains some sample code to how you might create a "Chart Generator Tool" to make it easier to generate new charts.

    What you can and can't do with charts:

    • A chart must be based on 1 table, and 1 table only. You can't combine data from multiple tables.
    • You have two basic chart types: Points or Columns.
    • You can have any colour as long as you want green.
    • Charts can use one of two operators: Sum or Count.
    • You can only apply static filters in charts, i.e. you must type in (hardcode) the filter when you generate the chart.

    The layout of a chart:

    A chart has a simple layout. You choose the table to base it on, then a field from that table to show along the X-Axis, and - if needed - a filter on this table. Then you select what data from the table to show on the Y-Axis (also called Measure). A measure can be based on Sum or Count. You can display multiple measures in the same chart.

    This is what your charts could look like:

    Charts

    Showing a chart:

    Charts can only be displayed in the new NAV 2009 client. To display a chart, follow these steps:

    • Start the new client, then click on the "Customize" button in the top right corner (just left of the ?-button), and select "Customize this page".
    • From there you can add a new Chart part. So add one of them, move it left / right / up and down to where on the page you want it.
    • Click the "Customize Part"-button to select which chart to display. This button looks up into the Chart-table in NAV (table 2000000078) and lets you select a chart.

    Removing a chart:

    You can personalize the page again to remove a chart, or click "Restore Defaults" to remove any personalization. You can also remove any personalization (including any charts that a user has added) with the classic client, from table 2000000075 "User Metadata". This is the table that stores the personalization for each page for each user. Deleting a record from this table removes any personalization made to that page by that user.

    Chart objects:

    Charts are stored in system table 2000000078 "Chart". You can view them with form 9182 Charts, or from Administration -> Application Setup -> Role Tailored Client -> Charts.

    Charts are defined by xml documents which are stored as BLOB fields. You can export a chart to an xml document, then modify the xml document, and import it back as a new chart.

    This is an example of a chart definition:

    ChartDef

    The rules for the xml documents are:


    • You must specify exactly one Table ID.
    • You can only have one X-Axis.
    • You can only have one Filters-element, but it can contain multiple Filter-elements.
    • You can only have ony Y-Axis, but it can contain multiple measures.
    • Measure operator must be either Count or Sum.

    Ideas for a Chart Generator Tool (CGT):

    Modifying xml documents can be tedious. But it can be made easier with tools. Below, I have put some sample NAV code, how such a tool could be made.

    Note !!!! ===
    The code below is only supplied as an example of how such a tool could be made. It is completely un-supported and to be used at your own risk and responsibility.

    ====

    The code below is provided in Text format. When importing text objects into NAV directly, you will not get any warnings whether to overwrite existing objects. So each object has been deliberately changed by adding [RemoveMe] in front of each Object ID. This would have to be removed, after reviewing each Object type and number, to check that it would not overwrite any existing objects!

    This is how the tool would work:

    the tool contains the following objects:

    Type    ID    Name
    1    72000    Chart Generator
    1    72001    Chart Generator Filter
    1    72003    Chart Generator YAxis
    2    72000    Chart Generator List
    2    72001    Chart Filters
    2    72003    YAxis List
    2    72004    Chart Generator Card
    5    72000    Chart Generator Mgt

    Charts can be generated from form 72004 "Chart Generator Card":

    Hit F3 to create a new chart. Enter ID and a Name. As a minimum you must specify Title, "Table ID", "X-Axis Field Name", and one or more Y-Axis fields. Once you have specified the chart definition, then click on Chart -> "Generate Chart". This will automatically either update an existing chart, or generate a new chart in table 2000000078, ready to be used from the new client.

    The following example shows how to create a chart to show Inventory for certain items:

    1. Create a new chart (F3) from the Chart Generator card. As ID, specify INVENTORY.
    2. As name, also enter Inventory.
    3. Set Table ID = 27 (Item).
    4. Leave Type as Column, and select what to display along the X-Axis - let's choose Description.
    5. Click on Chart -> Y-Axis (or drill down on the "YAxis Fields"-field). This is where we choose the measure, in our case Inventory. So look up in the field "Y-Axis Measure Field ID" and select Inventory.
    6. Leave the Caption, and the "Measure operator" to their default values, and go back to the Card Generator form.
    7. Finally, to avoid showing 100s of items on the chart, click on chart -> Filters.
    8. In the Filters-list, look up in the field "Filter Field ID" and select "No.", then enter a filter value of 70000|70001|70002|70003

    Now the definition of the chart is done. To make it available in the new client, click chart -> Generate Chart (F11). If you want to change the chart definition, then just make the necessary changes from the "Chart Generator Card", then hit F11 again to update the existing chart.

    Now the chart will be available for the new client as described above. If you update the chart, then the new client will use the new chart definition next time you restart it.

    These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use.

    Lars Lohndorf-Larsen (Lohndorf)
    Microsoft Dynamics UK
    Microsoft Customer Service and Support (CSS) EMEA

    === sample code only ===

    === 

    Updated 19/10 2008

    Updated version of the tool on this post:

    3D charts. Chart Generator tool II 

    This version of the tool also has Z-axis for 3D charts

    ===

     

    OBJECT Table [RemoveMe]72000 Chart Generator

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=09:13:04;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        OnInsert=BEGIN

                   IF Chart.GET(Company,ID) THEN

                     ERROR('Chart already exists in table 2000000078. Run form 9182 and delete it, or use a different ID.');

                 END;

     

        LookupFormID=Form72000;

      }

      FIELDS

      {

        { 1   ;   ;Company             ;Text30         }

        { 2   ;   ;ID                  ;Code20        ;NotBlank=Yes }

        { 10  ;   ;Name                ;Text50        ;OnValidate=BEGIN

                                                                    Title := Name;

                                                                  END;

                                                                   }

        { 11  ;   ;Title               ;Text50         }

        { 15  ;   ;Type                ;Option        ;OptionString=Column,Point }

        { 16  ;   ;Table ID            ;Integer       ;OnValidate=BEGIN

                                                                    MODIFY;

                                                                  END;

                                                                   }

        { 17  ;   ;Table Name          ;Text30        ;FieldClass=FlowField;

                                                       CalcFormula=Lookup(Object.Name WHERE (Type=CONST(Table),

                                                                                             ID=FIELD(Table ID)));

                                                       Editable=No }

        { 20  ;   ;XAxis Field ID      ;Integer        }

        { 21  ;   ;XAxis Field Name    ;Text80        ;OnValidate=BEGIN

                                                                    IF "XAxis Field Name" <> '' THEN BEGIN

                                                                      FieldRec.SETRANGE(TableNo,"Table ID");

                                                                      FieldRec.SETRANGE(FieldName,"XAxis Field Name");

                                                                      FieldRec.FINDFIRST;

                                                                      "XAxis Field ID" := FieldRec."No.";

                                                                      "XAxis Field Name" := FieldRec.FieldName;

                                                                      "XAxis Field Caption" := FieldRec."Field Caption";

                                                                      "XAxis title" := FieldRec."Field Caption";

                                                                    END ELSE BEGIN

                                                                      "XAxis Field ID" := 0;

                                                                      "XAxis Field Name" := '';

                                                                      "XAxis Field Caption" := '';

                                                                      "XAxis title" := '';

                                                                    END;

                                                                  END;

                                                                   }

        { 22  ;   ;XAxis Field Caption ;Text80         }

        { 23  ;   ;XAxis title         ;Text80         }

        { 24  ;   ;Show Title          ;Boolean       ;InitValue=Yes }

        { 30  ;   ;YAxis fields        ;Integer       ;FieldClass=FlowField;

                                                       CalcFormula=Count("Chart Generator YAxis" WHERE (Company=FIELD(Company),

                                                                                                        ID=FIELD(ID)));

                                                       Editable=No }

      }

      KEYS

      {

        {    ;Company,ID                              ;Clustered=Yes }

      }

      FIELDGROUPS

      {

      }

      CODE

      {

        VAR

          Chart@1000 : Record 2000000078;

          FieldRec@1102601000 : Record 2000000041;

     

        BEGIN

        END.

      }

    }

     

    OBJECT Table [RemoveMe]72001 Chart Generator Filter

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=16:44:37;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        OnInsert=BEGIN

                   TESTFIELD("Filter Field ID");

                 END;

     

      }

      FIELDS

      {

        { 1   ;   ;Company             ;Text30         }

        { 2   ;   ;ID                  ;Code20         }

        { 3   ;   ;Line No.            ;Integer        }

        { 10  ;   ;Filter Field ID     ;Integer       ;OnValidate=BEGIN

                                                                    IF "Filter Field ID" <> 0 THEN BEGIN

                                                                       ChartGen.GET(Company,ID);

                                                                       ChartGen.TESTFIELD("Table ID");

                                                                       FieldRec.GET(ChartGen."Table ID","Filter Field ID");

                                                                       "Filter Field Name" := FieldRec.FieldName;

                                                                    END ELSE

                                                                       "Filter Field Name" := '';

                                                                  END;

                                                                   }

        { 11  ;   ;Filter Field Name   ;Text30         }

        { 15  ;   ;Filter Value        ;Text30         }

      }

      KEYS

      {

        {    ;Company,ID,Line No.                     ;Clustered=Yes }

      }

      FIELDGROUPS

      {

      }

      CODE

      {

        VAR

          ChartGen@1102601001 : Record 72000;

          FieldRec@1102601000 : Record 2000000041;

     

        BEGIN

        END.

      }

    }

     

    OBJECT Table [RemoveMe]72003 Chart Generator YAxis

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=07:26:24;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        OnInsert=BEGIN

                   TESTFIELD("YAxis Measure Field ID");

                 END;

     

        LookupFormID=Form72003;

        DrillDownFormID=Form72003;

      }

      FIELDS

      {

        { 1   ;   ;Company             ;Text30         }

        { 2   ;   ;ID                  ;Code20         }

        { 3   ;   ;Line No.            ;Integer        }

        { 10  ;   ;YAxis Measure Field ID;Integer      }

        { 11  ;   ;YAxis Measure Field Caption;Text30  }

        { 12  ;   ;Mearure Operator    ;Option        ;OptionString=Sum,Count }

        { 20  ;   ;Show Title          ;Boolean        }

      }

      KEYS

      {

        {    ;Company,ID,Line No.                     ;Clustered=Yes }

      }

      FIELDGROUPS

      {

      }

      CODE

      {

     

        BEGIN

        END.

      }

    }

     

    OBJECT Form [RemoveMe]72000 Chart Generator List

    {

      OBJECT-PROPERTIES

      {

        Date=12/08/08;

        Time=06:50:19;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        Width=16500;

        Height=6710;

        TableBoxID=1;

        SourceTable=Table72000;

      }

      CONTROLS

      {

        { 1   ;TableBox     ;220  ;220  ;16060;5500 ;HorzGlue=Both;

                                                     VertGlue=Both }

        { 2   ;TextBox      ;0    ;0    ;4400 ;0    ;HorzGlue=Both;

                                                     Visible=No;

                                                     ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr=Company }

        { 3   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=2;

                                                     InColumnHeading=Yes }

        { 4   ;TextBox      ;0    ;0    ;1700 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr=ID }

        { 5   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=4;

                                                     InColumnHeading=Yes }

        { 6   ;TextBox      ;0    ;0    ;4400 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr=Name }

        { 7   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=6;

                                                     InColumnHeading=Yes }

        { 8   ;TextBox      ;0    ;0    ;4400 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr=Title }

        { 9   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=8;

                                                     InColumnHeading=Yes }

        { 10  ;TextBox      ;0    ;0    ;550  ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr=Type }

        { 11  ;Label        ;0    ;0    ;0    ;0    ;ParentControl=10;

                                                     InColumnHeading=Yes }

        { 12  ;TextBox      ;0    ;0    ;1700 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="Table ID" }

        { 13  ;Label        ;0    ;0    ;0    ;0    ;ParentControl=12;

                                                     InColumnHeading=Yes }

        { 14  ;CommandButton;4400 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Default=Yes;

                                                     PushAction=LookupOK;

                                                     InvalidActionAppearance=Hide }

        { 15  ;CommandButton;6820 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Cancel=Yes;

                                                     PushAction=LookupCancel;

                                                     InvalidActionAppearance=Hide }

        { 16  ;CommandButton;14080;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     PushAction=FormHelp }

        { 17  ;MenuButton   ;9240 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     CaptionML=ENU=Chart;

                                                     Menu=MENUITEMS

                                                     {

                                                       { ID=18;

                                                         PushAction=RunObject;

                                                         CaptionML=ENU=Filters;

                                                         RunObject=Form 72001;

                                                         RunFormLink=Company=FIELD(Company),

                                                                     ID=FIELD(ID) }

                                                       { ID=20;

                                                         PushAction=RunObject;

                                                         CaptionML=ENU=XAxis;

                                                         RunObject=Form 72002;

                                                         RunFormLink=Field1=FIELD(Company),

                                                                     Field2=FIELD(ID) }

                                                       { ID=21;

                                                         PushAction=RunObject;

                                                         CaptionML=ENU=YAxis;

                                                         RunObject=Form 72003;

                                                         RunFormLink=Company=FIELD(Company),

                                                                     ID=FIELD(ID) }

                                                     }

                                                      }

        { 19  ;MenuButton   ;11660;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     CaptionML=ENU=F&unctions;

                                                     Menu=MENUITEMS

                                                     {

                                                       { ID=22;

                                                         PushAction=RunObject;

                                                         ShortCutKey=F11;

                                                         CaptionML=ENU=Generate Chart;

                                                         RunObject=Codeunit 72000 }

                                                     }

                                                      }

      }

      CODE

      {

        VAR

          Chart@1000 : Record 2000000078;

     

        BEGIN

        END.

      }

    }

     

    OBJECT Form [RemoveMe]72001 Chart Filters

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=09:21:22;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        Width=12150;

        Height=6710;

        TableBoxID=1;

        SourceTable=Table72001;

        AutoSplitKey=Yes;

        DelayedInsert=Yes;

      }

      CONTROLS

      {

        { 1   ;TableBox     ;220  ;220  ;11710;5500 ;HorzGlue=Both;

                                                     VertGlue=Both }

        { 2   ;TextBox      ;0    ;0    ;1700 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="Filter Field ID";

                                                     OnLookup=BEGIN

                                                                ChartGen.GET(Company,ID);

                                                                ChartGen.TESTFIELD("Table ID");

                                                                FieldRec.SETRANGE(TableNo,ChartGen."Table ID");

     

                                                                IF FORM.RUNMODAL(FORM::"Field List",FieldRec) = ACTION::LookupOK THEN

                                                                  VALIDATE("Filter Field ID",FieldRec."No.");

                                                              END;

                                                               }

        { 3   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=2;

                                                     InColumnHeading=Yes }

        { 4   ;TextBox      ;0    ;0    ;4400 ;0    ;HorzGlue=Both;

                                                     ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="Filter Field Name" }

        { 5   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=4;

                                                     InColumnHeading=Yes }

        { 6   ;TextBox      ;0    ;0    ;4400 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="Filter Value" }

        { 7   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=6;

                                                     InColumnHeading=Yes }

        { 8   ;CommandButton;4890 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Default=Yes;

                                                     PushAction=LookupOK;

                                                     InvalidActionAppearance=Hide }

        { 9   ;CommandButton;7310 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Cancel=Yes;

                                                     PushAction=LookupCancel;

                                                     InvalidActionAppearance=Hide }

        { 10  ;CommandButton;9730 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     PushAction=FormHelp }

      }

      CODE

      {

        VAR

          ChartGen@1000 : Record 72000;

          FieldRec@1001 : Record 2000000041;

     

        BEGIN

        END.

      }

    }

     

    OBJECT Form [RemoveMe]72003 YAxis List

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=07:31:05;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        Width=10000;

        Height=6710;

        TableBoxID=1;

        SourceTable=Table72003;

        AutoSplitKey=Yes;

        DelayedInsert=Yes;

      }

      CONTROLS

      {

        { 1   ;TableBox     ;220  ;220  ;9560 ;5500 ;HorzGlue=Both;

                                                     VertGlue=Both }

        { 2   ;TextBox      ;0    ;0    ;1700 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="YAxis Measure Field ID";

                                                     OnLookup=BEGIN

                                                                ChartGen.GET(Company,ID);

                                                                ChartGen.TESTFIELD("Table ID");

                                                                FieldRec.SETRANGE(TableNo,ChartGen."Table ID");

     

                                                                IF FORM.RUNMODAL(FORM::"Field List",FieldRec) = ACTION::LookupOK THEN BEGIN

                                                                  "YAxis Measure Field ID" := FieldRec."No.";

                                                                  "YAxis Measure Field Caption" := FieldRec."Field Caption";

                                                                END;

                                                              END;

                                                               }

        { 3   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=2;

                                                     InColumnHeading=Yes }

        { 4   ;TextBox      ;0    ;0    ;4400 ;0    ;HorzGlue=Both;

                                                     ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="YAxis Measure Field Caption" }

        { 5   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=4;

                                                     InColumnHeading=Yes }

        { 6   ;TextBox      ;0    ;0    ;550  ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     SourceExpr="Mearure Operator" }

        { 7   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=6;

                                                     InColumnHeading=Yes }

        { 8   ;CheckBox     ;0    ;0    ;1700 ;0    ;ParentControl=1;

                                                     InColumn=Yes;

                                                     ShowCaption=No;

                                                     SourceExpr="Show Title" }

        { 9   ;Label        ;0    ;0    ;0    ;0    ;ParentControl=8;

                                                     InColumnHeading=Yes }

        { 10  ;CommandButton;2740 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Default=Yes;

                                                     PushAction=LookupOK;

                                                     InvalidActionAppearance=Hide }

        { 11  ;CommandButton;5160 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     Cancel=Yes;

                                                     PushAction=LookupCancel;

                                                     InvalidActionAppearance=Hide }

        { 12  ;CommandButton;7580 ;5940 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     PushAction=FormHelp }

      }

      CODE

      {

        VAR

          ChartGen@1000 : Record 72000;

          FieldRec@1001 : Record 2000000041;

     

        BEGIN

        END.

      }

    }

     

    OBJECT Form [RemoveMe]72004 Chart Generator Card

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=08:17:28;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        Width=16170;

        Height=6490;

        SourceTable=Table72000;

      }

      CONTROLS

      {

        { 1   ;TabControl   ;220  ;220  ;15730;5280 ;HorzGlue=Both;

                                                     VertGlue=Both;

                                                     PageNamesML=ENU=General }

        { 4   ;TextBox      ;3850 ;990  ;2750 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr=ID }

        { 5   ;Label        ;440  ;990  ;3300 ;440  ;ParentControl=4 }

        { 6   ;TextBox      ;3850 ;1650 ;5500 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     NextControl=12;

                                                     SourceExpr=Name }

        { 7   ;Label        ;440  ;1650 ;3300 ;440  ;ParentControl=6 }

        { 8   ;TextBox      ;3850 ;2200 ;5500 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr=Title }

        { 9   ;Label        ;440  ;2200 ;3300 ;440  ;ParentControl=8 }

        { 10  ;TextBox      ;3850 ;3520 ;2750 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr=Type }

        { 11  ;Label        ;440  ;3520 ;3300 ;440  ;ParentControl=10 }

        { 12  ;TextBox      ;3850 ;2860 ;1700 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr="Table ID";

                                                     OnLookup=BEGIN

                                                                Object.SETRANGE(Type,Object.Type::Table);

                                                                IF FORM.RUNMODAL(FORM::Objects,Object) = ACTION::LookupOK THEN

                                                                  "Table ID" := Object.ID;

                                                              END;

     

                                                     OnAfterValidate=BEGIN

                                                                       CALCFIELDS("Table Name");

                                                                     END;

                                                                      }

        { 13  ;Label        ;440  ;2860 ;3300 ;440  ;ParentControl=12 }

        { 21  ;TextBox      ;12980;990  ;2750 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     NextControl=1102601000;

                                                     SourceExpr="XAxis Field Name";

                                                     OnLookup=BEGIN

                                                                TESTFIELD("Table ID");

                                                                FieldRec.SETRANGE(TableNo,"Table ID");

     

                                                                IF FORM.RUNMODAL(FORM::"Field List",FieldRec) = ACTION::LookupOK THEN

                                                                  VALIDATE("XAxis Field Name",FieldRec.FieldName);

                                                              END;

                                                               }

        { 22  ;Label        ;9570 ;990  ;3300 ;440  ;ParentControl=21 }

        { 20  ;TextBox      ;12980;1650 ;2750 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr="XAxis Field Caption" }

        { 23  ;Label        ;9570 ;1650 ;3300 ;440  ;ParentControl=20 }

        { 24  ;CheckBox     ;12980;2750 ;440  ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     ShowCaption=No;

                                                     SourceExpr="Show Title" }

        { 25  ;Label        ;9570 ;2750 ;3300 ;440  ;ParentControl=24 }

        { 27  ;TextBox      ;12980;2200 ;2750 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr="XAxis title" }

        { 28  ;Label        ;9570 ;2200 ;3300 ;440  ;ParentControl=27 }

        { 1102601000;TextBox;12980;3410 ;1700 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr="YAxis fields" }

        { 1102601001;Label  ;9570 ;3410 ;3300 ;440  ;ParentControl=1102601000 }

        { 1102601002;TextBox;5720 ;2860 ;3630 ;440  ;ParentControl=1;

                                                     InPage=0;

                                                     SourceExpr="Table Name" }

        { 14  ;CommandButton;13750;5720 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     PushAction=FormHelp }

        { 15  ;MenuButton   ;11330;5720 ;2200 ;550  ;HorzGlue=Right;

                                                     VertGlue=Bottom;

                                                     CaptionML=ENU=&Chart;

                                                     Menu=MENUITEMS

                                                     {

                                                       { ID=16;

                                                         PushAction=LookupTable;

                                                         ShortCutKey=F5;

                                                         CaptionML=ENU=L&ist }

                                                       { ID=26;

                                                         PushAction=RunObject;

                                                         CaptionML=ENU=Filters;

                                                         RunObject=Form 72001;

                                                         RunFormLink=Company=FIELD(Company),

                                                                     ID=FIELD(ID) }

                                                       { ID=17;

                                                         PushAction=RunObject;

                                                         CaptionML=ENU=YAxis;

                                                         RunObject=Form 72003;

                                                         RunFormLink=Company=FIELD(Company),

                                                                     ID=FIELD(ID) }

                                                       { ID=18;

                                                         MenuItemType=Separator }

                                                       { ID=19;

                                                         PushAction=RunObject;

                                                         ShortCutKey=F11;

                                                         CaptionML=ENU=Generate Chart;

                                                         RunObject=Codeunit 72000 }

                                                     }

                                                      }

      }

      CODE

      {

        VAR

          FieldRec@1001 : Record 2000000041;

          Object@1002 : Record 2000000001;

          XAxisField@1000 : Text[30];

     

        BEGIN

        END.

      }

    }

     

    OBJECT Codeunit [RemoveMe]72000 Chart Generator Mgt

    {

      OBJECT-PROPERTIES

      {

        Date=19/08/08;

        Time=16:47:56;

        Modified=Yes;

        Version List=CGT;

      }

      PROPERTIES

      {

        TableNo=72000;

        OnRun=BEGIN

                CreateXML(Rec);

     

                MESSAGE('Chart %1 was created / updated.',Chart.ID);

              END;

     

      }

      CODE

      {

        VAR

          Chart@1015 : Record 2000000078;

          ChartGen@1003 : Record 72000;

          ChartFilters@1008 : Record 72001;

          ChartYAxis@1012 : Record 72003;

          "3TierMgt"@1013 : Codeunit 419;

          XMLDoc@1000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v4.0'.DOMDocument";

          DomNode@1001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMNode";

          DomNode2@1006 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMNode";

          DomTextNode@1002 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF87-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMText";

          DomAttribute@1004 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF85-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMAttribute";

          DomNodeList@1009 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF82-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMNodeList";

          DomProcessInstruction@1005 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{2933BF89-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v4.0'.IXMLDOMProcessingInstruction";

          NameSpace@1007 : Text[80];

          i@1010 : Integer;

          TempFileName@1014 : Text[250];

          Debug@1016 : Boolean;

          DebugFileName@1102601000 : Text[250];

          IStream@1102601001 : InStream;

     

        PROCEDURE CreateXML@1(ChartGenerator@1000 : Record 72000);

        BEGIN

          //=== Enable debug and filename to save the xml document to disk

          Debug := FALSE;

          DebugFileName := '';

          //===

     

          CREATE(XMLDoc);

          XMLDoc.async(FALSE);

     

          // Initialize document and set namespaces

          NameSpace := 'urn:schemas-microsoft-com:dynamics:NAV:MetaObjects';

     

          DomNode := XMLDoc.createNode(1,'ChartDefinition',NameSpace);

          DomAttribute := XMLDoc.createAttribute('xmlns:xsd');

          DomAttribute.value := 'http://www.w3.org/2001/XMLSchema';

          DomNode.attributes.setNamedItem(DomAttribute);

          DomAttribute := XMLDoc.createAttribute('xmlns:xsi');

          DomAttribute.value := 'http://www.w3.org/2001/XMLSchema-instance';

          DomNode.attributes.setNamedItem(DomAttribute);

     

          // add chart type

          DomAttribute := XMLDoc.createAttribute('Type');

          CASE ChartGenerator.Type OF

            ChartGenerator.Type::Column:

              DomAttribute.value := 'Column';

            ChartGenerator.Type::Point:

              DomAttribute.value := 'Point';

          END;

          DomNode.attributes.setNamedItem(DomAttribute);

          XMLDoc.appendChild(DomNode);

     

          AddNode('ChartDefinition','Title','');

          AddNode('ChartDefinition/Title','Text',ChartGenerator.Title);

          AddAttribute('ChartDefinition/Title/Text','ID','ENU');

          AddNode('ChartDefinition','Table','');

          AddAttribute('ChartDefinition/Table','ID',FORMAT(ChartGenerator."Table ID"));

          AddNode('ChartDefinition/Table','Filters','');

     

          // Filters

          ChartFilters.SETRANGE(Company,ChartGenerator.Company);

          ChartFilters.SETRANGE(ID,ChartGenerator.ID);

          IF ChartFilters.FINDSET THEN

            REPEAT

              AddNode('ChartDefinition/Table/Filters','Filter','');

              AddNode('ChartDefinition/Table/Filters/Filter','Field','');

              AddAttribute('ChartDefinition/Table/Filters/Filter/Field','Name',ChartFilters."Filter Field Name");

              AddNode('ChartDefinition/Table/Filters/Filter','Value',ChartFilters."Filter Value");

            UNTIL ChartFilters.NEXT = 0;

     

          // XAxis

          ChartGenerator.TESTFIELD("XAxis Field Name");

     

          AddNode('ChartDefinition','XAxis','');

          AddAttribute('ChartDefinition/XAxis','ShowTitle',BooleanFormat(ChartGenerator."Show Title")); ///

          AddNode('ChartDefinition/XAxis','Title','');

          AddNode('ChartDefinition/XAxis/Title','Text',ChartGenerator."XAxis title");

          AddAttribute('ChartDefinition/XAxis/Title/Text','ID','ENU');

          AddNode('ChartDefinition/XAxis','Field','');

          AddAttribute('ChartDefinition/XAxis/Field','Name',ChartGenerator."XAxis Field Name");

     

          // YAxis

          ChartYAxis.SETRANGE(Company,ChartGenerator.Company);

          ChartYAxis.SETRANGE(ID,ChartGenerator.ID);

          IF ChartYAxis.FINDSET THEN BEGIN

            AddNode('ChartDefinition','YAxis','');

            AddAttribute('ChartDefinition/YAxis','ShowTitle',BooleanFormat(ChartYAxis."Show Title"));

            AddNode('ChartDefinition/YAxis','Measures','');

     

            REPEAT

              AddNode('ChartDefinition/YAxis/Measures','Measure','');

              AddAttribute('ChartDefinition/YAxis/Measures/Measure','Operator',FORMAT(ChartYAxis."Mearure Operator"));

              AddNode('ChartDefinition/YAxis/Measures/Measure','Field','');

              AddAttribute('ChartDefinition/YAxis/Measures/Measure/Field','Name',FORMAT(ChartYAxis."YAxis Measure Field Caption"));

            UNTIL ChartYAxis.NEXT = 0;

          END;

     

          TempFileName := TEMPORARYPATH + '\' + FORMAT(CREATEGUID) + '.xml';

     

          XMLDoc.save(TempFileName);

     

          IF NOT Chart.GET(ChartGenerator.Company,ChartGenerator.ID) THEN BEGIN

            Chart.Company := ChartGenerator.Company;

            Chart.ID := ChartGenerator.ID;

            Chart.Name := ChartGenerator.Name;

            Chart.INSERT;

          END;

          Chart.BLOB.IMPORT(TempFileName);

          Chart.MODIFY;

     

          IF Debug THEN

            XMLDoc.save(DebugFileName);

     

          // Clean up

          IF EXISTS(TempFileName) THEN

            ERASE(TempFileName);

          CLEAR(DomNode);

          CLEAR(XMLDoc);

        END;

     

        PROCEDURE AddNode@2(AddToNode@1000 : Text[120];NodeName@1001 : Text[120];NodeValue@1002 : Text[120]);

        BEGIN

          DomNodeList := XMLDoc.selectNodes(AddToNode);

          DomNode := DomNodeList.item(DomNodeList.length - 1);

     

          DomNode2 := XMLDoc.createNode(1,NodeName,NameSpace);

          DomTextNode := XMLDoc.createTextNode(NodeValue);

          DomNode2.appendChild(DomTextNode);

          DomNode.appendChild(DomNode2);

        END;

     

        PROCEDURE AddAttribute@3(AddToNode@1000 : Text[120];AttributeName@1001 : Text[120];AttributeValue@1002 : Text[120]);

        BEGIN

          DomNodeList := XMLDoc.selectNodes(AddToNode);

          DomNode := DomNodeList.item(DomNodeList.length - 1);

     

          DomAttribute := XMLDoc.createAttribute(AttributeName);

          DomAttribute.value := AttributeValue;

          DomNode.attributes.setNamedItem(DomAttribute);

        END;

     

        PROCEDURE BooleanFormat@4(Boo@1000 : Boolean) : Text[30];

        BEGIN

          IF Boo THEN

            EXIT('true');

     

          EXIT('false');

        END;

     

        EVENT XMLDoc@1000::ondataavailable@198();

        BEGIN

        END;

     

        EVENT XMLDoc@1000::onreadystatechange@-609();

        BEGIN

        END;

     

        BEGIN

        END.

      }

    }

     

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 - Sample C# project to consume a NAV web service

    • 2 Comments

    This post is a step-by-step guide, how to make a very simple C# project (3 lines of code) to integrate to NAV 2009 via a web service.

    == Blog updated on 21/01 2009:

    Line added in the sample code below, to avoid error “Path property must be set before calling the Send method” when making an update via the web service

    ==

     

    For simplicity, make a new codeunit in NAV with one function, for example like this:

     

    OBJECT Codeunit 78000 Test Web Service
    {
      OBJECT-PROPERTIES
      {
        Date=15/08/08;
        Time=07:40:24;
        Modified=Yes;
        Version List=;
      }
      PROPERTIES
      {
        OnRun=BEGIN
              END;

      }
      CODE
      {

        PROCEDURE AddX@1102601000(Value@1102601000 : Text[30]) : Text[30];
        BEGIN
          EXIT(Value + 'x');
        END;

        BEGIN
        END.
      }
    }

     

    The function just adds 'x' to whatever Text-parameter you give it, and returns the new value.

     

    Publishing this codeunit as a web service is a simple as just specifying it in form 810 "Web Services", giving it a name - for example "TestWebService" and tick "Publish".

    Before you continue, check that your new web service is available by going to this link in your internet browser (modify it to match your system):

    http://[MachineName]:[Port]/[InstanceName]/ws/[CompanyName]/Services, for example 

    http://MyMachine:7047/DynamicsNAV/ws/CRONUS_International_Ltd./Services

    If you can't see your new web service here, then first check if the "Microsoft Dynamics NAV Business Web Services"-service is running. Then (re)start it and check in the application log which port it is listening to. For more details about publishing a Web Service from NAV, go to this post: "NAV 2009 - How to publish a web service". 

     

    When you can see that your web service is available, then you are finished with NAV. The rest of the work happens in Visual Studio (VS). You can use either VS2005 or 2008. Follow these steps:

    1)  After opening VS, select File -> New -> Project. Select a Visual C# project, and  under templates, select a "Windows Forms Application" (in VS2005 it is just called "Windows Application").

    2)  This step depends a bit on whether you use VS2005 or 2008. In VS2005, just rightclick on "References" in the Solution Explorer, and select "Add Web Reference". In VS2008, to get to the same place, rightclick on "References", then select "Add Service Reference", then click the Advanced button, and then click the "Add Web Reference" button.

    3)  In URL, enter the link to your web services - the same link as above, and click "Go". This will list available web services. Find your TestWebService, and click on "View Service". The Web reference name defaults to the machine name. Change that to "WS", and then click the "Add Reference" button.

    4)  Now to the C# code. Open the Toolbox and add a  button and two TextBoxes to your form, then doubleclick on the button to get to the code. This is the code that you need:

    WS.TestWebService NAVWebService = new WS.TestWebService();

    NAVWebService.UseDefaultCredentials = true;

    // Line below added 21/1 2009:

    NAVWebService.Url = "http://[MachineName]:7047/DynamicsNAV/WS/CRONUS_International_Ltd./Codeunit/TestWebService";

    textBox2.Text = NAVWebService.AddX(textBox1.Text);

     

    This is what the first line refers to:

    WS: The name you gave to your reference in step 3.

    TestWebService: This is the name of the you typed into form 810 in NAV.

    NAVWebService: This is the name that you assign. You could call it anything.

    5)  Now run the project (F5), enter something into TextBox1, and hit the button.

     

     

    Lars Lohndorf-Larsen (Lohndorf )

    Microsoft Dynamics UK


    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 - How to publish a web service

    • 2 Comments

    This posts only describes how you can publish a web service in Microsoft Dynamics NAV (which is easy enough), and how you can see what you published. It does not describe how you can actually use this web service. Future posts will describe this.

    Please note that the features described here are only available in NAV 2009, which is not released yet. For more details about NAV 2009, follow this link:

    NAV 2009 Technical Preview

     

    The short story:

    In NAV 2009, run form 810 "Web Services". Select either a page or a codeunit, then click "Publish". The page or codeunit selected is now published as a web service.

    And, a few more details: 

    First of all, make sure to start the service "Microsoft Dynamics NAV Business Web Services". This is the service that handles web service requests. It runs from the same folder as the service "Microsoft Dynamics NAV Server", which handles requests from the new client.

    Then check the application log, to
      1) Make sure that the service started OK
      2) See what port it is listening to
    Currently, the service will listen to port 7047. But this has changed and may change again, so just check the application log for an entry like this:

    Service MicrosoftDynamicsNavWS is listening to requests at http://[MachineName]:7047/[InstanceName].

    Open your Internet browser and go to this site:
    http://[MachineName]:7047/InstanceName/WS/CRONUS_International_Ltd./Services
    The site name is built by taking the link from the application log (see above), and then adding /WS/[CompanyName]/Services
    Note that in the comapny name, space is replaced with _ (underscore). In my case - running on a machine called TEST - the link is:

    http://TEST:7047/InstanceName/ws/CRONUS_International_Ltd./Services

    Your internet browser should now show a page like this:

     
    - <discovery xmlns="http://schemas.xmlsoap.org/disco/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <contractRef ref=http://TEST:7047/InstanceName/ws/CRONUS_International_Ltd/SystemService xmlns="http://schemas.xmlsoap.org/disco/scl/" />
      </discovery>
     

    It lists just one service called SystemService. The next step is to add a service from NAV:

      1) Start a classic client, open Object Designer, and run form 810 "Web Services".
      2) Select Object Type = Page, Object ID = 21, Service Name = Customer Card, and tick "Published".

    Go back to your internet browser and refresh, and you should see your new service.


    To see details of this service, copy the link into the address bar of your browser - in my case:
    http://TEST:7047/InstanceName/ws/CRONUS_International_Ltd/Page/Customer_Card

    This shows you all interfaces to this service. You will notice that this web service exposes the fields from the customer card page. In addition to this, it exposes the following system functions:

    Read
    ReadMultiple
    Create
    CreateMultiple
    Update
    UpdateMultiple
    Delete


    These are the functions that are available on any web service which is based on a page.


    As indicated by the available object types in form 810 "Web Services", you can base a web service on either a page or on a codeunit. So just repeat the steps above, but select "Codeunit" instead of "Page" in "Object Type" in form 810 to publish a codeunit.

     

    A web service is a method of integration based on a common framework. So a developer who knows about web services can now use your NAV webservices to develop integration without knowing anything about NAV. When using a NAV web service, it will run the same triggers as if the page or codeunit was used from a NAV client. More posts and examples will follow on this blog, about how to consume the web services that you have now published.

     

    Lars Lohndorf-Larsen (Lohndorf)
    Microsoft Dynamics UK


    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    How to deploy multiple NAS’es in ADCS

    • 0 Comments

    Although this is not related to the ‘core C/Side’, I would discuss about configuring ADCS with multiple NASes.

    The first question would by why somebody would like to do this? The answer is very simple. On a single VT100 NAS installation, whenever a handheld user is performing a time-consuming task, any other handheld user will have to wait for the task to complete, before getting a response in the screen. The reason is because the NAS can perform one task at a time, and while it is busy, it will queue any other incoming requests. Another good reason is because the VT100 will round-robin the available NASes making the up-time more reliable.

    The installation is simple, as long as you configure the system like this (TCP ports are examples):

    ADCS with multiple NASes

    For security reasons, it is recommended that the Access Point uses encryption (to the handhelds), and that this sub-network is private between the handhelds and the VT100.

    The NASes can be on the same machine or on different boxes, as long as you remember to set up the registry correctly where the VT100 service is installed. If the NASes are on different boxes, remember to generate an encryption key per box, and to copy the public key to the corresponding entry in the registry of the VT100 box. Of course the installation gets simplified if the NASes run on the same box, and even more if the VT100 and the NASes share the same hardware.

    Let’s make a step by step installation (assuming a NAV 5.00 or 5.00 SP1).

    1.       Install the Software (Database + NAS + VT100 + C/Side) as described in the manual.

    2.       Run C/Side using Windows Authentication. Remember to use the same credentials that the NAS will get (else the encryption key cannot be read by the NAS).

    3.       Generate the encryption key (one per machine – not per NAS).

    4.       Set each NAS to connect to the corresponding (same for all NASes) database, company, etc, using the same Windows login credentials as you logged in to generate the encryption keys.

    5.       Because of a VT100 limitation, each NAS will have to get a different TCP port number, even if they are located on different machines, so, the startupparameter should be “ADCS ADCSID=#”, where # refers to a different TCP port.

    6.       Now, the really tricky part comes from here. For each NAS that the VT100 will connect to (that is, on the machine where the VT100 service will run) you will need an entry in the registry, in order to connect the VT100 with the corresponding NAS. Each entry should be under “HKEY_LOCAL_MACHINE\SOFTWARE\Navision\ADCS\Application Servers”. The ADCS installation will create “ADCSNAS1”, and you can continue creating an entry per NAS on the same level (let’s say “ADCSNAS2, ADCSNAS3”, etc).

    7.       If the NAS is on a different machine than the VT100, you also need to set the ‘SocketServerName’ and portnumber, where the first one refers to the machine name (or IP address) of the host of the corresponding NAS, and the second one, the portnumber (i.e. 11322). Both of these keys are ‘String Value’.

    8.       For each NAS, you will need the ‘CryptBlockSize’, ‘Key Size’ and ‘Public Key’ (the ‘Private Key’ should not be copied), and this ‘Public Key’ should be copied from the machine where the NAS is hosted.

    a.       NOTE- The machine that hosts the VT100 will need one ‘ADCSNAS’ entry per NAS that it connects to, but the machine(s) that hosts several NASes will only need one ‘ADCSNAS’ that will share the same keys (generated by the C/Side client), but different ADCSID startupparameter.

    9.       Now you should start the NASes and the VT100 services on the corresponding machines. To test that everything works as it should, you should be able to stop any of the NASes on your system, and the screens should not halt (however, the response time might be slower). Also, when not all NASes are available, new sessions might not be successful, but any existing ones should be fine.

    With this configuration you benefit on the simultaneous response time for the handhelds, as different NASes will be able to process in parallel even when the NASes are hosted on the same machine. Also, as discussed before, this helps minimize down times, as even when a NAS stops or gets restarted, the VT100 will retry from the ‘pool of NASes’ when a TCP timeout occurs. Because of this, don’t set NASes on the registry that will not be deployed, as this will in fact slow down the system.

    Jorge Alberto Torres (jtorres)
    Software Developer Engineer

  • Microsoft Dynamics NAV Team Blog

    Overview of platform updates for NAV 5

    • 0 Comments

    For a table of platform updates and hotfix history for NAV version 5 with build numbers, update numbers and file contents, follow this link:

    Overview of platform updates for NAV 5

    This previous post contains the same information for NAV 4 SP3:

    Overview of platform updates for NAV 4 SP3

     

    Lars Lohndorf-Larsen (Lohndorf)
    Microsoft Dynamics UK
    Microsoft Customer Service and Support (CSS) EMEA

Page 37 of 43 (637 items) «3536373839»