Working with Temporary Files in Dexterity

David Meego - Click for blog homepageKeeping with the theme of my previous post, I have another "Temporary" topic to discuss.

Dexterity developers sometimes need to write out files (usually text files) to a location.  This could be for a variety of purposes, including:

  • to create a file for integration into an external application in Extensible Markup Language (.XML), Tab delimited (.TXT), Comma Separated Variable (.CSV) or Hypertext Markup Language (.HTML) format.
  • to write a Macro (.MAC) file to be executed on-the-fly. 
  • to write a Batch (.BAT) file with commands to be run at the command prompt level.

The problem is that we need a location that we have write permissions to. Remember that UAC (User Access Control) could prevents us using the application folder.  We also need a location that is not used by other users, so we can avoid two users clashing if they try to create the same file at the same time in the same location.

That situation is fairly easily solved by creating the file in the user's temporary (TEMP) folder.  But how do we know what the path is to the temporary folder from inside Dexterity.

Well, if you are using Dexterity 11.0 for Microsoft Dynamics GP 2010, the answer is really simple.  There is a new function library command File_GetTempDirectory() that returns the path in Native format. For example: "C:\Users\{UserName}\AppData\Local\Temp\ ". 

Note: You might need to convert this path to Generic format with Path_MakeGeneric() for some functions.  Make sure you read the Dexterity Help File to understand which functions need a Generic format pathname.


So, what can you do if you are using an older version of Dexterity?

You can call out to a Win32 function to ask the operating system to get the temp folder path and pass it back to you. This article will discuss the methods involved for this technique as they can be used for other calls to the Win32 library DLL (Dynamic Link Library) files available in Windows.

To achieve this there are 2 steps, but I normally make it into 3 steps by adding a wrapper function to simplify the calls:

  1. Create a prototype procedure for the call.
  2. Create a wrapper function for the call.
  3. Call the wrapper function.

Before we can start, we need to know the parameters of the Win32 function we wish to use, usually a quick search will find the MSDN page for you. 

In our case https://msdn.microsoft.com/en-us/library/aa364992(VS.85).aspx gives the following syntax:

DWORD WINAPI GetTempPath(
__in DWORD nBufferLength,
__out LPTSTR lpBuffer
);

Note: We are going to use the ANSI version of the command as we don't support unicode (double byte).  So this is the GetTempPathA() function.

Step 1: Prototype Procedure

The prototype procedure is a global procedure named the same as the Win32 function and having the same parameters as the Win32 function.  Notice the addition of the long integer as the first parameter to capture the returned status from the Win32 function.

Note: In our case the GetTempPathA@kernel32.dll global procedure already exists in the core Dynamics.dic dictionary and so we can skip this step.

Global Procedure: GetTempPathA@kernel32.dll

 {GetTempPathA@kernel32.dll} 

out    long    lStatus;
in  long    lLength;
inout   string  sPath;

Step 2: Wrapper Function

The wrapper function calls the prototype procedure using the extern command and provides a nice user friendly interface for our code to use.  Including the MSDN link as a comment is handy if you need to reference the page again.

Global Function: GetTempPath

 {GetTempPath}

function returns string OUT_Path;

local long l_ret;
local 'String A 255' l_path;
local long l_len = 255;

{ https://msdn2.microsoft.com/en-us/library/Aa364992.aspx }

extern 'GetTempPathA@kernel32.dll', l_ret, l_len, l_path;

OUT_Path = l_path;

Step 3: Calling the Function 

Now we have our wrapper function in place, we can call it as desired. 

Code Example

 { Get Temporary Folder Path in Generic format } 

warning Path_MakeGeneric(GetTempPath()); 

A final point. Always remember to delete your temporary files when you have finished with them.

I hope you find this article useful as it explains both how to get the path to the user's temporary folder and the method for calling external Win32 DLLs.

David

// Copyright © Microsoft Corporation. All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, https://opensource.org/licenses/ms-pl.html.)