Lucas Branisso
Lucas Branisso

Reputation: 1

How can I connect to a SSAS server using a different user from my windows login using ADOMD.NET?

I need to retrieve some data from an SSAS cube. I was given an user, service.user, with which I can connect to the cube using Excel like this: Excel login

But I need to do this programmatically. Research led me to de ADOMD.NET library. I tried to use it in a couple of different approaches but couldn't get it to work

First, I tried this C# snippet (.NET 8):

using Microsoft.AnalysisServices.AdomdClient;

try {
    using (AdomdConnection conn = new("Data Source=bi.mycompany.com; Initial Catalog=MyDb; UID=mycompany\\service.user; PWD=pass")) {
        conn.Open();
        Console.WriteLine(conn.ServerVersion);

        foreach (var cube in conn.Cubes) {
            Console.WriteLine(cube.Name);
        }
        conn.Close();
    }
} catch (Exception ex) {
    Console.WriteLine(ex.ToString());
} finally {
    Console.WriteLine("Press any key");
    Console.ReadKey();
}

This failed with (original was in portuguese, I tried translating it): Microsoft.AnalysisServices.AdomdClient.AdomdErrorResponseException: The user 'MYCOMPANY\my.user' does not have access to database 'MyDB' or datababase does not exist.

Note that the error says 'MYCOMPANY\my.user', which I use to log in to my Windows machine, not "service.user". After some googling I've found that ADOMD.NET ignores UID and PWD and uses the current logged in user to authenticate requests to SSAS. To work around this it was suggested to impersonate service.user, which I tried to do like this (this was generated with AI, but looks similar to other posts):

class Program
{
    // Correct P/Invoke for LogonUser
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
                                        int dwLogonType, int dwLogonProvider, out IntPtr phToken);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);

    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    public static void Main()
    {
        string username = "service.user";
        string password = "pass";
        string domain = "mycompany";

        IntPtr tokenHandle = IntPtr.Zero;

        // Use LogonUser to authenticate the other user
        bool success = LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out tokenHandle);

        if (success)
        {
            // Create a WindowsIdentity using the token
            using (WindowsIdentity identity = new WindowsIdentity(tokenHandle))
            {
                // Run code as the impersonated user
                WindowsIdentity.RunImpersonated(identity.AccessToken, () =>
                {
                    try
                    {
                        // Open the AdomdConnection under the impersonated user's context
                        using (AdomdConnection conn = new AdomdConnection("Data Source=bi.mycompany.com; Initial Catalog=MyDb"))
                        {
                            conn.Open();
                            Console.WriteLine("Connection opened successfully as " + identity.Name);
                            Console.WriteLine(conn.ServerVersion);

                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Failed to connect: " + ex.Message);
                    }
                });
            }
            // Clean up: Close the token handle
            CloseHandle(tokenHandle);
        }
        else
        {
            Console.WriteLine("LogonUser failed. Error: " + Marshal.GetLastWin32Error());
        }
    }
}

This time the error was: Unhandled exception. System.IO.FileNotFoundException: File name: 'Microsoft.AnalysisServices.AdomdClient, Version=19.86.2.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91'

I tried granting Read and Execute permissions for service.user in my .nuget folder, as suggested here, but got the same error.

Is it possible to connect to SSAS with another user programmatically the same way I can connect using Excel?

Also, this code would eventually run on a Linux machine, would it work there?

Upvotes: 0

Views: 49

Answers (0)

Related Questions