Share via


RPC server Unavailable

Question

Thursday, November 29, 2012 1:57 PM

I have a utility which list all the services on a specified machine and provide flexibility to start/stop those services. Now suppose i am on domain D1. Utility 's listing me services on any machine which is on same Domain i.e. D1. OK great!!

I use VPN to connect to another domain D2. I have admin account on D2 (D2\Username & password). I can successfully RDP a machine M1 with these credentials. Now machine M1 have some services which i want to control with the help of my utility. Since my utility is on D1, so i tried to run it on my machine using D2\Username & password but i am getting following error :

Debugging result:

Now how can i overcome this problem?

Specs:

My Machine Specs (Client on D1) : Windows 7 Enterprise SP1 64 bit.

M1 Specs (Server on D2) : Windows Server 2008 R2 Standard.

Cheers, Anuj

All replies (8)

Thursday, December 6, 2012 3:03 PM âś…Answered | 2 votes

Hi Anuj,

Please try this sample code.  

thanks

Frank K [MSFT]

/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 2012.  Microsoft Corporation.  All rights reserved.
++*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.ServiceProcess;

namespace ImpersonateStop
{
    class Program
    {
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        [DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        public extern static bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

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

        static void Main(string[] args)
        {
            if (args.Length != 5)
            {
                Console.WriteLine("ImpersonateStop [user] [domain] [password] [service to stop] [server]");
                return;
            }

            try
            {
                IntPtr hToken = IntPtr.Zero;

                if (!LogonUser(args[0], args[1], args[2], LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref hToken))
                {
                    Console.WriteLine("LogonUser failed with {0}", Marshal.GetLastWin32Error());
                    return;
                }

                WindowsIdentity impWI;

                impWI = new WindowsIdentity(hToken);

                Console.WriteLine("User: {0}", impWI.User.ToString());
                Console.WriteLine("Name: {0}", impWI.Name.ToString());

                WindowsPrincipal winprin = new WindowsPrincipal(impWI);

                if (winprin.IsInRole("administrators"))
                    Console.WriteLine("is an ADMIN");
                else
                    Console.WriteLine("Not an ADMIN");

        
                
                WindowsImpersonationContext ImpersonationContext;

                ImpersonationContext = impWI.Impersonate();

               

                // running as impersonated user
                ServiceController sc = new ServiceController(args[3], args[4]);

                sc.Stop();

                Console.WriteLine("{0} was stopped", args[3]);

                // stop the impersonation
                ImpersonationContext.Undo();

                CloseHandle(hToken);
            }
            catch (Exception e)
            {
                Console.WriteLine("{0}", e.ToString());
            }
        }
    }
}

Friday, November 30, 2012 7:14 AM

Hi AnujAg,

I'm trying to involve some senior engineers into this issue and it will take some time. Your patience will be greatly appreciated.

Thanks.

Bob Shen [MSFT]
MSDN Community Support | Feedback to us


Tuesday, December 4, 2012 8:51 AM

Hi Bob Shen,

Hope you please get some time to look into this.

Cheers, Anuj


Wednesday, December 5, 2012 12:50 AM

Hi Anuj,

This is not going to work.  You can't authenticate a D2 user in D1 if there is not trust between D1 and D2.  This is by design.  The error you are encountering is expected.

Can you tell me what API you are using to start and stop your service?  You are going to need to make some changes for this to work.  I'll need to know what API you are using.  You are essentially going to have to do like the following:

1. Impersonate the D2 user with LogonUser() using LOGON32_LOGON_NEW_CREDENTIALS.

2. Impersonate the D2 user

3. Start/stop the service.

This should work.

thanks

Frank K [MSFT]


Thursday, December 6, 2012 9:44 AM

Thanks Frank for helping.

We are using ServiceController class to connect the behavior (Start and Stop) of the services. This is under the namespace System.ServiceProcess; This class is using Win32 API.  Is that what you are asking for?

Here is the complete Source Code:

Source Code

Cheers, Anuj


Friday, December 7, 2012 1:52 PM

Perfect Frank .....This works like a Charm..

Thank you very very much...It's very helpful.

Cheers, Anuj


Monday, December 17, 2012 6:53 AM

Hey Frank/Bob,

I am facing a problem in accessing public queue in other domain.

My machine is in Domain D1 and I need to find the count of messages in message queue (public) at a machine/server in domain D2. I was using the above code, the following errors/exceptions are coming.

1) MessageQueue[] allprivatequeus = MessageQueue.GetPublicQueuesByMachine("Machine");
Error: A workgroup installation computer does not support the operation.

2)
MessageQueue[] allprivatequeus = MessageQueue.GetPrivateQueuesByMachine("Machine");
Error: Message Queue service is not available.//as no private queue exists.

3)
var mgmt = new MSMQManagement();
mgmt.Init("Machine", null, @"DIRECT=OS:Machine\queue");

Error: The Message Queuing service is not available

4)
mgmt.Init("Machine", @"DIRECT=OS:Machine\queue", null);

Error: This operation is not supported for Message Queuing installed in workgroup mode.

I uninstalled the MSMQ and re-Installed it checking the box 'Active Directory Domain Services Integration / Directory Service Integration' but still the MSMQ got installed in WorkGroup mode (Checked it in registory).

What could be done to access the count of messages in a public queue.

Please suggest a solution or workaround for the problem.

Thanks

Harbola


Tuesday, December 24, 2019 11:54 AM

Really helpful , thanks a lot

Divya