C# : ServiceController previliges problem

I'm using the following line to check for access to services on remote machine.
ServiceController[] _Services = ServiceController.GetServices(TbxIP.Value);

I get privileges exception using this line, but I don't have problem when accessing the remote machine using the services.msc.

(both commands are done from the same machine with admin privileges to the same remote machine.)
LVL 3
OrenRozenAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Sudhakar PulivarthiProject Lead - EngineeringCommented:
Hi,
When you want to access remote machine's SCM u have to provide the credentials. In ur case when ur trying to do through services.msc in ur machine the credentials for that remote machine might have been already stored in "Credential Manager". Hence it was possible with out providing the details.

But, when u want to achieve it programatically then u need to impersonate using remote user credentials before GetServices statement.
I am providing the impersonation code written in C#
internal enum LogonType : int
    {
        /// <summary>
        /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on  
        /// by a terminal server, remote shell, or similar process.
        /// This logon type has the additional expense of caching logon information for disconnected operations; 
        /// therefore, it is inappropriate for some client/server applications,
        /// such as a mail server.
        /// </summary>
        LOGON32_LOGON_INTERACTIVE = 2,

        /// <summary>
        /// This logon type is intended for high performance servers to authenticate plaintext passwords.
        /// The LogonUser function does not cache credentials for this logon type.
        /// </summary>
        LOGON32_LOGON_NETWORK = 3,

        /// <summary>
        /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without 
        /// their direct intervention. This type is also for higher performance servers that process many plaintext
        /// authentication attempts at a time, such as mail or Web servers. 
        /// The LogonUser function does not cache credentials for this logon type.
        /// </summary>
        LOGON32_LOGON_BATCH = 4,

        /// <summary>
        /// Indicates a service-type logon. The account provided must have the service privilege enabled. 
        /// </summary>
        LOGON32_LOGON_SERVICE = 5,

        /// <summary>
        /// This logon type is for GINA DLLs that log on users who will be interactively using the computer. 
        /// This logon type can generate a unique audit record that shows when the workstation was unlocked. 
        /// </summary>
        LOGON32_LOGON_UNLOCK = 7,

        /// <summary>
        /// This logon type preserves the name and password in the authentication package, which allows the server to make 
        /// connections to other network servers while impersonating the client. A server can accept plaintext credentials 
        /// from a client, call LogonUser, verify that the user can access the system across the network, and still 
        /// communicate with other servers.
        /// NOTE: Windows NT:  This value is not supported. 
        /// </summary>
        LOGON32_LOGON_NETWORK_CLEARTEXT = 8,

        /// <summary>
        /// This logon type allows the caller to clone its current token and specify new credentials for outbound connections.
        /// The new logon session has the same local identifier but uses different credentials for other network connections. 
        /// NOTE: This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
        /// NOTE: Windows NT:  This value is not supported. 
        /// </summary>
        LOGON32_LOGON_NEW_CREDENTIALS = 9,
    }

    /// <summary>
    /// This class provides a wrapper for impersonating a windows user.
    /// </summary>
    public class Impersonation : IDisposable
    {
        // Impersonation object to close later when requested.
        private IntPtr _userHandle;
        private WindowsImpersonationContext _impersonationContext;


        /// <summary>
        /// Starts the impersonate context for the credentials.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="domain">The domain.</param>
        /// <returns></returns>
        public bool StartImpersonate(string userName, string password, string domain)
        {
            // User machine token.
            _userHandle = IntPtr.Zero;

            //bool loggedOn = LogonUser("prateek.rathore", "SHIVA", "prtk33", 9, 0, out userHandle);
            bool loggedOn = LogonUser(userName, domain, password, 9, 0, out _userHandle);

            // Fails to log on to machine.
            if (!loggedOn)
            {                
                return false;
            }

            try
            {
                // Begin impersonating the user.
                _impersonationContext = WindowsIdentity.Impersonate(_userHandle);
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new Exception(ex.Message);
            }
            catch (OutOfMemoryException ex)
            {
                throw new Exception(ex.Message);
            }
            catch (SecurityException ex)
            {
                throw new Exception(ex.Message);
            }

            return true;
        }

        /// <summary>
        /// Stops the impersonate context.
        /// </summary>
        /// <returns></returns>
        public bool StopImpersonate()
        {
            // Clean up
            if (_userHandle != IntPtr.Zero)
            {
                CloseHandle(_userHandle);
                _userHandle = IntPtr.Zero;
            }

            if (_impersonationContext != null)
            {
                _impersonationContext.Undo();
                _impersonationContext.Dispose();
                _impersonationContext = null;
            }

            return true;
        }

        
        #region IDisposable Members

        public void Dispose()
        {
            // Call to close impersonation.
            StopImpersonate();
            // Suppress the call, not to include this object to finalization queue.
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="Impersonation"/> is reclaimed by garbage collection.
        /// </summary>
        ~Impersonation()
        {
            // Stop if it is not explicitly stopped.
            if (_userHandle != IntPtr.Zero)
            {
                StopImpersonate();
            }
        }

        #endregion


        // All Interop dlls.
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);
    }

Open in new window

// Impersonate the entry.
Impersonation impersonate = new Impersonation();
// Try to login into the system.
bool status = impersonate.StartImpersonate("UserName","Password","Domain");
// Successfully logged on.
if (status)
{
ServiceController[] _Services = ServiceController.GetServices(TbxIP.Value);
// Dispose the entry.
impersonate.StopImpersonate();
}

Open in new window

0
Russell_VenableCommented:
You should take a look at this project an learn from it

http://www.codeproject.com/KB/cs/svcmgr.aspx?display=Print
0
OrenRozenAuthor Commented:
just to make sure I understand and to clarify:
1. I'm logged in with the domain administrator account to a specific machine.
2. from that machine, I have no problem accessing 3 remote machines services using services.msc.
3. At the same time, using my code, I can access only 2 of the remote machines.

Won't my code use the credentials of the logged on administrator? why use impersonate with the same user account if I'm already logged in to that account?

Thanks.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Sudhakar PulivarthiProject Lead - EngineeringCommented:
Hi,
When an exe is launched it runs with the current logged in user account.
As far as i know we cannot get the password from the credential store. Hence we need to provide the details and also LogOnUser API requires password to get the access token to remote machine.
SCM is specific to the local user account of that machine. So when we want remotely access it, then the priviledge user of that machine can connect to it.
0
OrenRozenAuthor Commented:
appreciate your answer and I'll try the method you supplied to see if ti'll solve my problem.

just one last thing. what is the namespace for the Impersonation method?


0
Sudhakar PulivarthiProject Lead - EngineeringCommented:
Thank you Oren!
Impersonation is a custom class not a framework lib class. So u can directly keep under your project's namespace itself and use it.
0
Russell_VenableCommented:
Impersonation is part of the library. If you want to use impersonation without importing functions using interop and making a person class just to do it and less code. You need to use "System.Management" and or use ConnectionOptions or use "System.Security.Principle.WindowsImpersonationContext"

System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

ServiceController[] _Services = ServiceController.GetServices(TbxIP.Value);

//Your code to display

//End impersonation
impersonationContext.Undo();

Open in new window


Or you can use the WMI method using Management. You can use impersonation here as well if needed this one uses connection options.

using System;
using System.Management;  
namespace WMIQuery_CS
{
	class Main
	{
		static void Main(string[] args)
		{           
			GetWMIStats();
			Console.ReadLine();
		}

		static void GetWMIStats()
		{
			//Connection credentials to the remote computer - 
			//logged in account  must have adminstrator access for a remote machine
			ConnectionOptions oConn = new ConnectionOptions();
			//oConn.Username = "username";
			//oConn.Password = "password";
			string remoteMachineName="localhost";
			System.Management.ManagementScope oMs = new System.Management.ManagementScope("\\\\" +remoteMachineName , oConn);      
			 // pass the name of the service to query
			System.Management.RelatedObjectQuery oQuery = 
				new System.Management.RelatedObjectQuery("Win32_Service.Name='Alerter'");	 
			ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs,oQuery);
			ManagementObjectCollection oReturnCollection = oSearcher.Get();   
 	 
			foreach( ManagementObject oReturn in oReturnCollection ) 
				{				 
				Console.WriteLine("Name : " + oReturn["Name"].ToString());		 
				}   						
		}		 
	}
}

Open in new window


There is a lot of way to get what your looking for these ate just a few.


      ...      
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Sudhakar PulivarthiProject Lead - EngineeringCommented:
Hi Russell,
Impersonation concept is part of framework, but i was speaking about the class which i had implemented. There is no framework class called Impersonation.
0
OrenRozenAuthor Commented:
Hi,

I've added Sudhakar-Pulivarthi impersonation method to my code and hope test it today at the customer site.

will reply with the results.

Thanks.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.