Click here to Skip to main content
15,907,149 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am using the following code for the service
C#
namespace WindowsService
{
    public partial class MyWinService : ServiceBase
    {
        public MyWinService()
        {
            InitializeComponent();
            if (!System.Diagnostics.EventLog.SourceExists("DoLogSource"))
                System.Diagnostics.EventLog.CreateEventSource("DoLogSource", "LogSource");
            eventLog1.Source = "DoLogSource";
            eventLog1.Log = "LogSource";
        }

        protected override void OnStart(string[] args)
        {

            FileStream fs = new FileStream(@"c:\cWindowsService.txt",
            FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine("mcWindowsService: Service Started \n");
            m_streamWriter.Flush();
            m_streamWriter.Close(); 
            ManagementClass mc = new ManagementClass("Win32_Process");
            ManagementObjectCollection moc = mc.GetInstances();
            //ManagementObject mo = default(ManagementObject);
            string processDomain = null;
            string processUser = null;
            foreach(ManagementObject mo in moc)
            {
               ROOT.CIMV2.Process p = new ROOT.CIMV2.Process(mo);

               p.GetOwner(out processDomain, out processUser);
                if ((p.Name.ToString().Trim() == "explorer.exe"))
                {
                    System.Diagnostics.TextWriterTraceListener myfile = new System.Diagnostics.TextWriterTraceListener("C:\\UserName.txt");
                    Trace.Listeners.Add(myfile);
                    myfile.WriteLine(processUser);
                    m_streamWriter.WriteLine("Logged in User: "+processUser+"\n");
                    break;
                }
            }

        }
Posted
Comments
Oleksandr Kulchytskyi 4-Jun-12 8:08am    
On which account NT service running? (Local system / or from user name)

And on which OS it running?
Tirthankar Dutta 4-Jun-12 10:06am    
its runing in local system and the os is windows server 08
Tirthankar Dutta 4-Jun-12 10:07am    
waiting for your valuable suggestions.
Oleksandr Kulchytskyi 4-Jun-12 10:20am    
Since invention of Vista OS, all service , which running in Local System account, run in separate session, and has differs from your currently logged on user desktop. So you could change service account to run in appropriate user enviroment.
Tirthankar Dutta 5-Jun-12 2:21am    
Can u kindly explain how may I get the user name??

1 solution

Hi.
This is my answer to yours question:
"Can u kindly explain how may I get the user name??" For reaching necessary result you need to use WinApi and P/Invoke.
General workflow will be the next:

1) Call WTSGetActiveConsoleSessionId() to get the active console session id (VERY important, as the interactive session is NOT always session 1, even on client systems). This API will also return a -1 if there is no active user logged into the interactive session (that is, logged in locally to the physical machine, as opposed to using RDP).
2) Pass the session id from the previous API call to WTSQueryUserToken() to get an open token that reprents the user logged into the console.
3) Call DuplicateTokenEx() to convert the impersonation token (from WTSQueryUserToken) into a primary token.
4) Call CreateEnvironmentBlock() to create a new environment for the process (optional, but if you don't, the process won't have one).
5)Impersonate user using primary user token from step #3 and impersonate user:
C#
WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate.DangerousGetHandle());
 impersonationContext = tempWindowsIdentity.Impersonate();


5) Invoke Method GetProcessInfoByPID(....) *see in the of solution*

6)If you created an environment block, then you need to call DestroyEnvironmentBlock, otherwise you will generate a memory leak. The process is given a separate copy of the environment block when it launches, so you are only destroying local data.

C#
public static string GetProcessInfoByPID(int PID, out string User, out string Domain)
{
    User = String.Empty;
    Domain = String.Empty;
    OwnerSID = String.Empty;
    string processname = String.Empty;
    try
    {
        ObjectQuery sq = new ObjectQuery
            ("Select * from Win32_Process Where ProcessID = '" + PID + "'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
        if (searcher.Get().Count == 0)
            return OwnerSID;
        foreach (ManagementObject oReturn in searcher.Get())
        {
            string[] o = new String[2];
            //Invoke the method and populate the o var with the user name and domain
            oReturn.InvokeMethod("GetOwner", (object[])o);

            //int pid = (int)oReturn["ProcessID"];
            processname = (string)oReturn["Name"];
            //dr[2] = oReturn["Description"];
            User = o[0];
            if (User == null)
                User = String.Empty;
            Domain = o[1];
            if (Domain == null)
                Domain = String.Empty;
            string[] sid = new String[1];
            oReturn.InvokeMethod("GetOwnerSid", (object[])sid);
            OwnerSID = sid[0];
     return OwnerSID;
        }
    }
    catch
    {
        return OwnerSID;
    }
    return OwnerSID;
}
 
Share this answer
 
v2
Comments
Oleksandr Kulchytskyi 5-Jun-12 4:10am    
Solution above is a very tough for implementation, but very robust in practice.
Also it's possible to implement such functionality via WinApi method
WTSEnumerateProcesses, implementation of logic by using this WinApi methods seems much easier. But I'm not use it in practice ;)
Sandeep Mewara 5-Jun-12 10:50am    
5!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900