Build your own SAS client app with Microsoft .NET


As part of my follow-up to SAS Global Forum 2013, I've posted a few articles about how to create your own client apps with SAS Integration Technologies. This article shows how to use Microsoft .NET -- the same approach used for SAS Enterprise Guide and SAS Add-In for Microsoft Office -- to assemble a powerful client application.

About Microsoft .NET

Microsoft .NET, when accessed through Microsoft Visual Studio, offers a full application development platform. You can download Express editions of Microsoft Visual C# or Visual Basic .NET for free from the Microsoft website. However, if you want the best productivity with the tool, consider investing in one of the professional editions. If you're just getting started with Microsoft .NET, check out the many resources that Microsoft offers.

How to reference SAS Integration Technologies from Microsoft .NET

To create a Microsoft .NET project that can connect to a SAS environment with SAS Integration Technologies, follow these steps in Microsoft Visual Studio:

  1. Create a new project of any type, appropriate for your objective (for example, a Windows Forms application, Console application, or Windows Presentation Foundation application).
  2. In your Visual Studio project, add references to the following DLL files:
    • SASOManInterop.dll (for SAS Object Manager classes)
    • SASInterop.dll (for SAS Workspace classes)
    • SASOMIInterop.dll (for SAS Metadata Server classes)
    • SASIOMCommonInterop.dll (supports SASInterop.dll and SASOMIInterop.dll; not used directly in these examples)

    You can find these files in the installation folder for the SAS Integration Technologies client. For example: C:/Program Files/SAS/Shared Files/Integration Technologies or C:/Program Files/SASHome/x86/Integration Technologies.

Here's a screenshot of a Visual Studio project that contains these references:

About the sample application

As a companion to my SAS Global Forum paper, I have prepared a full sample application with these features:

  • connects to a SAS Workspace session using a server that you define in a dialog box.
  • allows you to connect to a local instance of SAS – no configuration required.
  • features three windows: a Program Editor, a log viewer, and a listing viewer. (Does that seem familiar?)
  • allows you to run a SAS program on a background thread, keeping the main user interface responsive.
  • retrieves the SAS log and listing output, and colors each line of output as appropriate (errors, warnings, notes, page boundaries).
  • Provides a simple data table viewer that supports filters.

Here is a screen capture of the application, named SAS Program Harness. It shows a program, the SAS log, and the listing output:

The sample application was built using Microsoft Visual Studio 2012. You can also use Microsoft Visual C# Express (which is free) to view, modify, and build the project. See the GitHub repository to download the project files: source code and ready-to-run binaries.

In future articles I'll focus on some implementation details such as connecting to servers, submitting programs, and viewing data. However, you don't have to wait! You can review the details within the paper right now, and examine the source code on GitHub.


About Author

Chris Hemedinger

Director, SAS User Engagement

+Chris Hemedinger is the Director of SAS User Engagement, which includes our SAS Communities and SAS User Groups. Since 1993, Chris has worked for SAS as an author, a software developer, an R&D manager and a consultant. Inexplicably, Chris is still coasting on the limited fame he earned as an author of SAS For Dummies


  1. Hi Chris,

    Another great blog post :)

    Would it be possible to add syntax highlighting to the program editor for your app, so it looks more like the enhanced editor (for us post release 6.12 folk)? Could you 'borrow' the dll from E.G. to do this in .NET??



    • Chris Hemedinger
      Chris Hemedinger on


      Unlike the SAS Integration Technologies client, the program editor is not available as a standalone component. It's installed with SAS for Windows, SAS Enterprise Guide, and a few other SAS applications -- but it isn't engineered (or licensed) as a building block for your own standalone apps. That said, it is possible to reuse the editor feature within custom tasks in EG, and my custom tasks book contains an example of that. It's on my backlog list to create a custom tasks example of this app, which I think would have some interesting uses.

  2. Hi ,

    I found your blog very good, but when i attempt to connect to a server with your client I do not even get the dialog box.

    I receive an unhandled exception?

    Does your client requires the whole SAS to be already installed on a workstation?

    Thank you

    • Chris Hemedinger
      Chris Hemedinger on

      You don't need SAS to be installed on your local PC, but you do need SAS Integration Technologies client, which installs with SAS Enterprise Guide or is available from the Downloads section on the SAS Support site. If you can share more details about the exception I might be able to help diagnose it.

  3. Hi Chris,

    I am trying to write programatically on current cursor position of SAS EG Editor progam window . I am able to write on open note window , data window but not able to write on Program editor window "FirstSasProgram.Sas". I am using below line of code

    foreach (Process p in System.Diagnostics.Process.GetProcesses())
      if (p.ProcessName.ToUpper().Contains("SEGUIDE"))
        this.WindowState = FormWindowState.Minimized;
        // Copy the text in the datafield to Clipboard
        Clipboard.SetText("First Sas Program", TextDataFormat.UnicodeText);
        IntPtr hWnd = p.MainWindowHandle;//FindWindow(null, " - Notepad");
        //  ShowWindow(hWnd, ShowWindowCommands.Show);
        // SetFocus(hWnd);
          //return    ;

    Please help if u can on this.

    Thanks & Regards

    • Chris Hemedinger
      Chris Hemedinger on


      The EG Editor is uses WPF, and not the traditional WinForms controls. This is probably why you cannot manipulate the cursor/characters in the way that you expect. Instead of your current approach, you might want to look at Windows UI Automation.

      Also, depending on what you are trying to do, you might be interested in AutoHotKey (a 3rd party app that you can script for keyboard commands) and the editor abbreviations and macro features, which allow you to script together hundreds of different program editor operations.

  4. Hi Chris,
    I need to find out current cursor position of SAS EG Editor progam window.
    Can you please help me how to approach for this using C#/ code.


    • Chris Hemedinger
      Chris Hemedinger on


      The program editor is part of SAS Enterprise Guide, and is not documented (or permitted) for use in a separately distributed application. EG does provide basic tools for including the editor as part of your own custom tasks that run within SAS Enterprise Guide, but not as a separate standalone application.

      If you can provide a little more information about what you're trying to do, I'll see if I can provide some guidance.

      • Hi Chris,

        Thanks for replying.

        Actually, we are required to operate SAS EG via .Net. The program we have created is able to edit SAS EG editor data through "Toolbar --> Add Ins" after we add the .Net DLL to it. However, if the user changes the current cursor position from end-of-file to somewhere in between, it does not work. We have tried using SASEnhanced Editor for this using the SAS.EnhancedEditor.presentation() class and explored the line and column properties of the same but have been unsuccessful. We have been in the process of troubleshooting this issue for long now. Kindly help.


        • Chris Hemedinger
          Chris Hemedinger on


          Again, you're straying into an area of use that isn't completely documented/supported for customers, but...

          You might try looking at the CaretMoved event in the EnhancedEditorControl class. That would notify you when the cursor moves. I would be interested to learn more about the nature of your custom task -- its purpose, and how it's working for you.

  5. Thanks Chris for the wonderful article,

    I tried executing this code, I got the following error

    An unhandled exception of type 'System.TypeLoadException' occurred in SASIOM.exe
    Additional information: Could not load type 'SAS.LanguageServiceCarriageControl' from assembly 'DemoSASIOM, Version=, Culture=neutral, PublicKeyToken=null'.

    Can you please advise what could be the problem.

    • Chris Hemedinger
      Chris Hemedinger on

      Dhanasekaran, it looks like you've built your own project -- and possibly you didn't copy the necessary SAS assemblies (DLLs) to where your project is running. In my project output directory, I have the following assemblies:

      04/26/2013  12:44 PM            30,720 SasHarness.exe
      04/26/2013  12:44 PM           188,416 SASInterop.dll
      04/26/2013  12:44 PM            32,768 SASIOMCommonInterop.dll
      04/26/2013  12:44 PM            49,152 SASOManInterop.dll

      The last three in that list are supplied with the SAS Integration Technologies client.

    • This took me 2 days to figure out. You need to make the target .net framework to 3.5 for the project. I had this error with the function activeSession.Workspace.LanguageService.FlushLogLines.

      My first thought that was that it could be a reference pointing to the wrong version but more testing showed that function Flushlines works though, so it had to had to be something else.

    • Alan Churchill on

      For others in the future who encounter this, it is not a .NET 3.5 dependency. Switch the Embed Interop Type to False on the SAS assemblies so that the assemblies are copied locally. I think this is alluded to but not specifically mentioned. Works fine in .NET 4.5 if you do that.

  6. Thanks a lot Chris for your reply.

    Infact I copied all those dlls you mentioned above in my project, but for some reason this was not getting included in the bin folder from where it picks and runs. After I change couple of options it worked fine.

  7. Chris, In the .Net+SAS application that I am developing, I am creating a singleton class to invoke SAS, so that the same instance would be available through out the session.

    The problem I am facing is, if there are any error in the SAS code, SAS will stop the processing. Even if I correct the code and submit, it is not running. Because it stopped due to an error in that session. Please advise an approach to fix this. What I am thinking is every time user hits "Run" button, I need to start a new instance of SAS.

    • Chris Hemedinger
      Chris Hemedinger on

      An error in the SAS code should not stop processing unless you have something like ABORT ABEND set, which would end the SAS session. That's not a good option for a SAS session that you want to persist. You should not need a new instance of SAS for each run -- and if you did, you would lose any WORK data or macro variable and options settings that had been set in a previous program. Plus, there is a bit of overhead in just creating a new SAS session, and you might not want your users to experience that penalty.

  8. Hi Chris,

    thanks for the code. My SAS server is setup as a Metadata Server. Do you know how I would modify your code to establish a connection with a SAS metadata server?


    • Chris Hemedinger
      Chris Hemedinger on

      With the Metadata server it's a multi-step process. I have an example in PowerShell, similar in approach to what you would do in .NET.

      Step 1. Connect to Metadata Server
      Step 2. Query metadata for the connection information about the SAS Workspace Server
      Step 3. Use this information to make a connection to the Workspace server (where you can access data and submit code).

    • Chris Hemedinger
      Chris Hemedinger on

      I doubt that there is a difference between the 32-bit and 64-bit Interop for JMP. You can generate your own Interop DLLs with the TLBIMP tool (part of the .NET SDK). You would have to run this on the COM server DLL for JMP -- I'm not sure what file that is, off the top of my head, but if you check the Windows registry for JMP references I'm sure you'll find it.

  9. can this application handle the relative path? if in the sas editor, enter a statement
    Like this


    Can this file be found?

    • Chris Hemedinger
      Chris Hemedinger on

      The %INCLUDE statement will find files in your SAS environment. If you want to include a file from your local PC, you would need to modify my application to read the contents of that file and then submit it to the remote SAS session. Not difficult, but this small example app doesn't have that feature built-in right now.

  10. Hello Chris, Thanks for your great articles on automating SAS with C#.

    We are using your sample as the basis for a company article.

    Have a Base SAS vs Enterprise Guide question...

    Our SAS Team built their scripts using the Enterprise Guide flavor of SAS (I'm not a SAS pro so hopefully I didn't mangle this) and our automation code seems to be trying to run the scripts under "Base SAS 9.4"

    We get an error like: does ERROR: The value 12SEP2016 is not a valid SAS name

    The scripts run fine from the Enterprise guide itself but when launched from our automation code we get this error.

    Is there a way to force the COM Automation libraries to use EG ?


    • Chris Hemedinger
      Chris Hemedinger on

      Rod, here's my guess without knowing the details of your app. You need to include OPTIONS VALIDVARNAME=ANY; as a startup statement in the SAS program/process you're running. EG sets that by default, but Base SAS does not -- it uses the "V7" setting which wouldn't allow "12SEP2016" as a variable name.

      Now..."12SEP2016" is an odd variable name -- perhaps a result of a transpose process of some date/transaction records.

      • Thanks chris! Yeah the name is a bit odd. It's a filename. I'm trying to get them to rename it to be SEP122016

        • Chris Hemedinger
          Chris Hemedinger on

          If that doesn't do the trick, include a PROC OPTIONS; RUN; sequence as part of the job, and compare the (long) output between Base SAS and EG. Other SAS system options can affect behavior, and your EG environment might trigger certain options differently than your straight-on Base SAS.

          • Thanks for the help. I'm gonna chat with the SAS coders about this issue. I think it is something overriding this setting,

  11. I've tried this solution and also with SAS Ole DB driver and getting the same error below. I'm using VS 2013 Premium and I'e installed SAS Integration Technologies. I've even run the Wizard from SAS integration technologies Configuration Wizard in which I can test SAS server connection. Even there I get the same error.
    System.Runtime.InteropServices.COMException (0x80042002):

    Not enough storage is available to complete this operation.


    • Chris Hemedinger
      Chris Hemedinger on

      Sounds like something else is missing. Check that you're using the correct port to connect to the SAS workspace. And is there encryption involved? Make sure that you also have the SAS/Secure client installed as well, if that's the case.

  12. Very cool... I'm fairly new to SAS but virtually every interesting thought I've had thus far has been mostly resolved by one of your many blogs or papers. So, thanks! I was also wondering if you know of an easy way to implement a .Net client of, say, a scoring engine deployed as a REST service? (e.g. by providing a Swagger contract or something along those lines)?

  13. I get a "Class not registered" exception when attempting to utilize any of the COM .dll's in Visual Studio C#. Is there a simple way to register these classes?

    (regsvr32.exe didn't like them: "The module SASInterop.dll was loaded but the entry-point DllRegisterServer was not found.")

    • Chris Hemedinger
      Chris Hemedinger on

      You don't register that Interop DLL. The SAS Integration Technologies client does have components that are registered when you install the client bundle, and by using these Interop DLLs in your .NET project, you don't need to know where those registered components are. If your .NET app can't find the components, it's probably because they either aren't installed OR because the version that is installed is a different bitness (example: you built a 64-bit SASHarness app but you have only the 32-bit SAS Int Tech client installed.) You can install both the 32- and 64-bit versions of the SAS IntTech client.

  14. Hi,

    I want to read a SAS file with visual studio .net c#, and insert the SAS file content into SQL table
    Is that possible?

  15. Very cool. while I was exploring,I tried to use SAS System Options under Windows such as "-config",Is it possible for me to use the powerful options?

    • Chris Hemedinger
      Chris Hemedinger on

      You cannot add startup options via this interface. If using this tool with local SAS, the SAS config options are determined by the "registered SAS command" in the Windows registry.

      For remote SAS workspace connections, the startup options are determined by the SAS Workspace Server definition in the SAS Metadata Server. It's typically an admin task to modify/maintain these.

      For any options that aren't strictly startup options, you can change these with the OPTIONS statement in a line of code.

      • Thanks a lot!
        I want to use different encoding methods to deal with different projects.
        By use sas.exe I can spacial -config "C:\Program Files\SASHome\SASFoundation\9.4\nls\zh\sasv9.cfg" to realize my needs.
        Is it possible to change the encoding via this interface?
        Or if there have another available interface to achieve my needs?

        • Chris Hemedinger
          Chris Hemedinger on

          No, ENCODING is a startup option and you can't change it from here. That has to be done at the SAS command line or in the config file chain. I guess you can't just use ENCODING UTF8 for your projects?

  16. SanthoshKumar Ravi on

    Hi Chris,

    I want a solution to connect to SAS Management console and access the libraries and collect the Users and Groups having access to the Libraries using C#. Please suggest the SAS management console is the only place to collect the information or is there any other way to collect the information using C#. In my scenario I am using C# to collect the information and store the data in tables in MS SQL server via SSIS (script task using C#). please share the C# code snippet to connect and get the details.

  17. Hi, Chris,
    It's seems that the dataviewer show the data without sas format, it's there any possible to bring the format from the raw data?
    Many thanks!

    • Chris Hemedinger
      Chris Hemedinger on

      It is possible by passing in some directives in when you open the data set. Sorry, I don't have an example handy -- but if I find one I'll post. Search the SAS Support site for "OLE DB Cookbook" for some examples.

  18. Hi Chris,

    I'd like to come up with a mobile app using Visual Studio that just pulls dashboard data. I have Xamarin installed in Visual Studio and when I create a new project I see about a dozen SAS references. But from this I don't see where to start coding on the Main entry point.

  19. I am integrating into my system but I am getting error the source I get from github shared link , can I get the process of doing it in the windows 10 system

  20. HI Chris

    I am getting the error SasHarnessSettings.xml not exists , it contains the server configurations

    private void ConnectToServer()
    SasServer activeSession = new SasServer();
    string settingsFile = Path.Combine(Application.LocalUserAppDataPath, appSettings);
    if (File.Exists(settingsFile))
    string xml = File.ReadAllText(settingsFile);
    activeSession = SasServer.FromXml(xml);

    Just want to know do I have to do any installation from sas in my system please clarify the setting I just added the dlls from "Integration Technologies" folder

    • Chris Hemedinger
      Chris Hemedinger on

      That code is meant to store and retrieve settings between sessions (server, port, user ID). It checks whether the settings file exists and then tries to load it if so. It shouldn't throw an error if the file doesn't exist -- it explicitly checks for the file first. If you're comfortable debugging I'd set a breakpoint in this method to see what's going on.

      • HI Chris

        That issue has been fixed after installing components from SAS for Integration technologies module , but now I am getting error while connecting to my sas database
        Error Message at code
        SASObjectManager.ServerDef obServerDef = new SASObjectManager.ServerDef
        Protocol = SASObjectManager.Protocols.ProtocolBridge,
        MachineDNSName = m,
        Port = Convert.ToInt32(pp)

        Message=Unable to cast COM object of type 'SASObjectManager.ServerDefClass' to interface type 'SASObjectManager.IServerDef2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{B7A1FC9A-72A6-4475-8896-0036C0FD468C}' failed due to the following error: No such interface supported (0x80004002 (E_NOINTERFACE)).
        at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease)
        at SASObjectManager.ServerDefClass.set_Protocol(Protocols Protocol)

        My function Code :
        SASObjectManager.ObjectFactory obOF = new SASObjectManager.ObjectFactory();
        SASObjectManager.ObjectKeeper obOK = new SASObjectManager.ObjectKeeper();
        SASObjectManager.ServerDef obServerDef = new SASObjectManager.ServerDef
        Protocol = SASObjectManager.Protocols.ProtocolBridge,
        MachineDNSName = m,
        Port = Convert.ToInt32(pp)
        }; -->error occur in this line

        SAS.Workspace obSAS = (SAS.Workspace)obOF.CreateObjectByServer(n, true, obServerDef, u, p);
        var ls = obSAS.LanguageService;
        obOK.AddObject(1, n, obSAS);
        OleDbConnection cn = new OleDbConnection
        ConnectionString = "Provider=sas.iomprovider; Data Source=iom-id://" + obSAS.UniqueIdentifier
        SAS.Libref libref;
        libref = obSAS.DataService.AssignLibref("STP", "", @"F:\SASData\STOREDPROCESSES", "");
        SAS.StoredProcessService sp = obSAS.LanguageService.StoredProcessService;
        sp.Repository = @"file:F:\SASData\STOREDPROCESSES";
        OleDbCommand cmd = cn.CreateCommand();
        cmd.CommandType = CommandType.Text;
        OleDbDataReader reader;
        cmd.CommandText = sql;
        reader = cmd.ExecuteReader();

        Please suggest

        • Chris Hemedinger
          Chris Hemedinger on

          Sounds like either something isn't completely registered OR it could be a .NET version thing. Are you using .NET Core by chance? Also make sure that the app you're building is targeting the same bit architecture as you have for SAS Integration Technologies client (x86 or x64).

          • Hi Chris,

            I am working with .NET Framework 5.0 windows application in c# , yes as you mentioned I tried in build the app target to 86 and 64 bit versions and any cpu options but it didnt work , my system version is windows 10 , 64 .
            Can you clarify is that SasInterops will work only any specific framework or environment

          • Chris Hemedinger
            Chris Hemedinger on

            I suggest trying to target a different .NET version. When I built this app I targeted 3.5 -- quite old now, but I haven't tried to update to a later one. It's possible some version differences are getting in the way.

  21. HI Chris

    You mean to say the component need to update in the .NET application or the Integration Technologies component as well , Can you please upgrade it new so that we use it any framework and will not get this issues because we have a application that needs to be migrated , And the update for your query testing in .NET 3.5 also didnt work

    Thanks you

    • Chris Hemedinger
      Chris Hemedinger on

      I'm not saying that it wouldn't work with a newer .NET -- it should. But I have not updated this particular example to prove that out. If it's not working for you even in .NET 3.5, something else is wrong. Lots of other people have successfully used this example, so something else must be at play in your setup.

  22. Just for confirmation the following dlls needs to be added from system folder

    And do we need to add anything in reference for the code and need to register in GAC

    please confirm because this is the error we have all the dll but getting error with com interop while creating connection

    • Chris Hemedinger
      Chris Hemedinger on

      Those DLLs should be in the application folder, they don't need to be in the GAC. And you can copy them from the SAS Integration Technologies client install directory.

      • Yes after I copied the installation folders from system into application folder now that line has been executed but next code am getting error I think its connection credentials issue can you please suggest if not credentials issue

        SAS.Workspace obSAS = (SAS.Workspace)obOF.CreateObjectByServer(n, true, obServerDef, u, p);


        Invalid pointer




        Note : I just modified the values with test account but I executed with what I got for sas database team

        • Chris Hemedinger
          Chris Hemedinger on

          In the directory with the IntTech client (ex: C:\Program Files\SASHome\x86\Integration Technologies), there is a tool called ITConfig2.exe. You can use that to test whether the connectivity to your server(s) is working. I'd make sure you've got that all working with the right values first.

  23. Hi Chris,

    Any chance of a .NET5 or .NET6 upgrade of these libraries on the horizon?


    • Chris Hemedinger
      Chris Hemedinger on

      Hi Henrik, I don't have a plan to update my examples here, but you should be able to use the referenced libraries with later versions of .NET.

Leave A Reply

Back to Top