473,414 Members | 1,738 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

Different set of properties in EnvironmentVariables when run in WindowService

Hi all,

When I run a normal application I can get who started a process with the
following example:

Process[] myProcesses = Process.GetProcesses();

foreach(Process p in myProcesses)
{
string user = p.StartInfo.EnvironmentVariables["username"];
}

But when I try to run exactly the same code within a WindowService as
System, the property "username" doesn't seem to exist anymore as an option
in the EnvironmentVariables!

Can anyone explain why it's so, and hopefully show how I can get this
information in some other way?

--
// Bjorn A
Nov 15 '05 #1
9 2436

"Bjorn Abelli" <bj**********@DoNotSpam.hotmail.com> wrote in message
news:el****************@TK2MSFTNGP10.phx.gbl...
Hi all,

When I run a normal application I can get who started a process with the
following example:

Process[] myProcesses = Process.GetProcesses();

foreach(Process p in myProcesses)
{
string user = p.StartInfo.EnvironmentVariables["username"];
}

But when I try to run exactly the same code within a WindowService as
System, the property "username" doesn't seem to exist anymore as an option
in the EnvironmentVariables!

Can anyone explain why it's so, and hopefully show how I can get this
information in some other way?


This is because you inherit your environment variables from your parent
process. A "normal application" is one launched by Explorer.exe, which adds
a bunch of environment variables.

Services aren't launched by Explorer, and don't have the same environment
variables.

You can try this intead:

System.Security.Principal.WindowsIdentity.GetCurre nt().Name

David
Nov 15 '05 #2

"David Browne" wrote...
"Bjorn Abelli" wrote...
When I run a normal application I can get who
started a process with the
following example:

Process[] myProcesses = Process.GetProcesses();

foreach(Process p in myProcesses)
{
string user = p.StartInfo.EnvironmentVariables["username"];
}

But when I try to run exactly the same code within a
WindowService as System, the property "username" doesn't
seem to exist anymore as an option
in the EnvironmentVariables!

Can anyone explain why it's so, and hopefully show how I can get this
information in some other way?

This is because you inherit your environment variables
from your parent process. A "normal application" is one
launched by Explorer.exe, which adds
a bunch of environment variables.

Services aren't launched by Explorer, and don't have
the same environment variables.


I should've been more clear in my question.

If you look again at the code example, you'll see that I'm not looking after
the username for the "current" process, but for who have started the other
processes on the machine.

[ System.Diagnostics.Process.GetProcesses() ]

Since *they* are launched by Explorer.exe, shouldn't they still have the
same environment variables, regardless of who's asking?

So my questions remain, though perhaps rephrased:

Why do the EnvironmentVariables for the *same* process differ depending on
if I ask for them from a "normal" application or from a service?

How can I fetch the username for another process from within a service?

// Bjorn A
Nov 15 '05 #3
If you run this code from your interactive logon session shell
(explorer.exe), EnvironmentVariables["username"] will return the value of
the INTERACTIVE "Username", from the session's shell environment block for
all processes ran from this shell (parent process environment block is
inheritted).
If you run this from a service, the environment value 'Username' doesn't
exists, because services do not have an associated interactive logon
session.

Willy.

"Bjorn Abelli" <bj**********@DoNotSpam.hotmail.com> wrote in message
news:OS**************@TK2MSFTNGP12.phx.gbl...

"David Browne" wrote...
"Bjorn Abelli" wrote...
When I run a normal application I can get who
started a process with the
following example:

Process[] myProcesses = Process.GetProcesses();

foreach(Process p in myProcesses)
{
string user = p.StartInfo.EnvironmentVariables["username"];
}

But when I try to run exactly the same code within a
WindowService as System, the property "username" doesn't
seem to exist anymore as an option
in the EnvironmentVariables!

Can anyone explain why it's so, and hopefully show how I can get this
information in some other way?

This is because you inherit your environment variables
from your parent process. A "normal application" is one
launched by Explorer.exe, which adds
a bunch of environment variables.

Services aren't launched by Explorer, and don't have
the same environment variables.


I should've been more clear in my question.

If you look again at the code example, you'll see that I'm not looking

after the username for the "current" process, but for who have started the other
processes on the machine.

[ System.Diagnostics.Process.GetProcesses() ]

Since *they* are launched by Explorer.exe, shouldn't they still have the
same environment variables, regardless of who's asking?

So my questions remain, though perhaps rephrased:

Why do the EnvironmentVariables for the *same* process differ depending on
if I ask for them from a "normal" application or from a service?

How can I fetch the username for another process from within a service?

// Bjorn A

Nov 15 '05 #4

"Bjorn Abelli" <bj**********@DoNotSpam.hotmail.com> wrote in message
news:OS**************@TK2MSFTNGP12.phx.gbl...

"David Browne" wrote...
"Bjorn Abelli" wrote...
When I run a normal application I can get who
started a process with the
following example:

Process[] myProcesses = Process.GetProcesses();

foreach(Process p in myProcesses)
{
string user = p.StartInfo.EnvironmentVariables["username"];
}

But when I try to run exactly the same code within a
WindowService as System, the property "username" doesn't
seem to exist anymore as an option
in the EnvironmentVariables!

Can anyone explain why it's so, and hopefully show how I can get this
information in some other way?

This is because you inherit your environment variables
from your parent process. A "normal application" is one
launched by Explorer.exe, which adds
a bunch of environment variables.

Services aren't launched by Explorer, and don't have
the same environment variables.


I should've been more clear in my question.

If you look again at the code example, you'll see that I'm not looking

after the username for the "current" process, but for who have started the other
processes on the machine.

[ System.Diagnostics.Process.GetProcesses() ]

Since *they* are launched by Explorer.exe, shouldn't they still have the
same environment variables, regardless of who's asking?

So my questions remain, though perhaps rephrased:

Why do the EnvironmentVariables for the *same* process differ depending on
if I ask for them from a "normal" application or from a service?


Ok. The BCL is confusing here. Process.StartInfo.EnvironmentVariables
always retrieves the environment for the current process. Period. It's
really intended for starting new processes, not examining existing
processes.

So the reason your service doesn't see that environment variable is that you
are always getting the environment of the current service process, which
doesn't have a username variable.

To read the environment of another process, you must read the VM of the
process. This is possible with Win32's ReadProcessMemory and appropriate
permissions, but the System.Diagnostics.Process type doesn't do it.
David
Nov 15 '05 #5
"Willy Denoyette [MVP]" ...
If you run this code from your interactive logon session
shell (explorer.exe), EnvironmentVariables["username"]
will return the value of the INTERACTIVE "Username",
from the session's shell environment block for all
processes ran from this shell (parent process environment
block is inheritted).
Ok, so in fact the environment variables I can get hold on *is* depending on
who is asking? That's to say that I can't check for other environment
variables than I can about my own process, *even* if the process in question
*is* started in an interactive session?

using System.Diagnostics;

...

Process[] myProcesses = Process.GetProcesses();
foreach(Process p in myProcesses)
{
// This always returns null when run from within
// a service, *even* if the process p *is* started
// from an interactive session...

string user = p.StartInfo.EnvironmentVariables["username"];
}
If you run this from a service, the environment value
'Username' doesn't exists, because services do not have
an associated interactive logon session.


Okey, I'll try to buy that even though I find it peculiar since there are
processes started by a user with a username...

But it still leaves my second question unanswered.

- How can I fetch the username for another
process from within a service?

Anyone?
// Bjorn A
Nov 15 '05 #6

- How can I fetch the username for another
process from within a service?


Using PInvoke, but then you will have some security issues to solve.
If you tell me on what OS you tend to run this I can give you some more
details how to solve these.

Willy.


Nov 15 '05 #7

"Willy Denoyette [MVP]" ...
- How can I fetch the username for another
process from within a service?


Using PInvoke, but then you will have some security
issues to solve. If you tell me on what OS you tend
to run this I can give you some more
details how to solve these.


I'd be very grateful for that. :-)

The OS is Windows XP (both Home and Pro).

// Bjorn A

Nov 15 '05 #8

"Bjorn Abelli" <bj**********@DoNotSpam.hotmail.com> wrote in message
news:u7**************@TK2MSFTNGP11.phx.gbl...

"Willy Denoyette [MVP]" ...
- How can I fetch the username for another
process from within a service?


Using PInvoke, but then you will have some security
issues to solve. If you tell me on what OS you tend
to run this I can give you some more
details how to solve these.


I'd be very grateful for that. :-)

The OS is Windows XP (both Home and Pro).

// Bjorn A


Bjorn,

Following two console samples:
- [1] uses the WIN32 API OpenProcessToken, but has problems to retrieve the
process identity for some processes (due to a lack of privileges).
[1]
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;
using System.Diagnostics;
using System.Security;
// Problem: proc.Handle property returns Access denied for 'idle' process
and,
// Cannot OpenProcessToken() for NT AUTHORITY\NETWORK SERVICE and NT
AUTHORITY\LOCAL SYSTEM
// Better use - WTSEnumerateProcesses on XP and higher
//

using HANDLE = System.IntPtr;
class IdentUser {

[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
HANDLE ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);

[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(HANDLE handle);

public const int TOKEN_QUERY = 0X00000008;
public static void Main() {

Process[] _process = Process.GetProcesses();
foreach(Process proc in _process)
{
try {
Console.WriteLine("Process Name :{0} \tProcess ID : {1} ",
proc.ProcessName, proc.Id);

DumpPrincipalName(proc.Handle);
Console.WriteLine("--------------------------------------------------");
}
catch(Exception ex)
{Console.WriteLine("Exception: {0}", ex.Message);}
}
}

static void DumpPrincipalName(HANDLE processHandle)
{
int access = TOKEN_QUERY;
HANDLE tokenHandle = IntPtr.Zero;
if ( 0 != OpenProcessToken( processHandle, access, ref tokenHandle ) )
{
WindowsIdentity wi = new WindowsIdentity(tokenHandle);
Console.WriteLine(wi.Name);
CloseHandle(tokenHandle); // Close process token
}
else
Console.WriteLine("Error OpenProcessToken:
{0}",Marshal.GetLastWin32Error());
}

}
- [2] uses the WTS API's which has not the same prblems as [1], but requires
XP or higher.

[2]

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
// Using Wtsapi32 (available on Windows.NET and XP)
// Get Process information using Terminal server API's
// Requirements: TCB privilege???
using HANDLE = System.IntPtr;
class ProcIdent {

[DllImport("wtsapi32", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool WTSEnumerateProcesses (
HANDLE ProcessHandle, // handle to process (from WTSOpenServer)
int Reserved, // dmust be 0
uint Version, // must be 1
ref IntPtr ppProcessInfo, // pointer to pointer to Processinfo
ref uint pCount // no. of processes
);

[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern IntPtr WTSOpenServer (
string ServerName // Server name (NETBIOS)
);

[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSCloseServer (
HANDLE hServer // Handle obtained by WTSOpenServer
);

[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSFreeMemory (
IntPtr pMemory );

[StructLayout(LayoutKind.Sequential)]
struct WTSProcessInfo {
internal uint SessionId;
internal uint ProcessId;
[MarshalAs(UnmanagedType.LPTStr)] internal string pProcessName;
internal IntPtr pUserSid;
}
[DllImport("advapi32", CharSet=CharSet.Auto)]
static extern bool ConvertSidToStringSid(
IntPtr pSID,
[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);

[DllImport("advapi32", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool LookupAccountSid
(
string lpSystemName, // name of local or remote computer
IntPtr pSid, // security identifier
StringBuilder Account, // account name buffer
ref int cbName, // size of account name buffer
StringBuilder DomainName, // domain name
ref int cbDomainName, // size of domain name buffer
ref int peUse // SID type
);
const int ERROR_NO_MORE_ITEMS = 259;

public static void Main() {
HANDLE hServer = IntPtr.Zero;
IntPtr pInfo = IntPtr.Zero;
IntPtr pInfoSave = IntPtr.Zero;
WTSProcessInfo WTSpi; // Reference to ProcessInfo struct
uint count = 0;
int iPtr = 0;
try {
hServer = WTSOpenServer(System.Environment.MachineName);
if(hServer == IntPtr.Zero)
Console.WriteLine(Marshal.GetLastWin32Error());
if (WTSEnumerateProcesses(hServer, 0, 1, ref pInfo, ref count))
{
pInfoSave = pInfo;
Console.WriteLine("Number of processes :{0}", count);
for(int n = 0; n < count; n++) {
WTSpi = (WTSProcessInfo) Marshal.PtrToStructure(pInfo,
typeof(WTSProcessInfo) );
iPtr = (int)(pInfo) + Marshal.SizeOf(WTSpi);
pInfo = (IntPtr)(iPtr);
if(WTSpi.ProcessId != 0)
Console.WriteLine(WTSpi.pProcessName + "\t" + WTSpi.ProcessId + "\t" +
DumpAccountFromSid(WTSpi.pUserSid));
else
Console.WriteLine("Idle pseudo proc");
}
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Free memory used by WTSEnumerateProcesses
WTSFreeMemory(pInfoSave);
// Close server handle
WTSCloseServer(hServer);
}
}

static string DumpAccountFromSid(IntPtr SID)
{
int cchAccount = 0;
int cchDomain = 0;
int snu = 0 ;
StringBuilder sb = new StringBuilder();

// Caller allocated buffer
StringBuilder Account= null;
StringBuilder Domain = null;
// Lookup account name on local system
// First call to get required buffer sizes
bool ret = LookupAccountSid(null, SID, Account, ref cchAccount, Domain,
ref cchDomain, ref snu);
if ( ret == true )
if ( Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS )
return "Error";
Account = new StringBuilder( cchAccount );
Domain = new StringBuilder( cchDomain );
ret = LookupAccountSid(null, SID, Account, ref cchAccount, Domain, ref
cchDomain, ref snu);
if (ret)
{
sb.Append(Domain);
sb.Append(@"\");
sb.Append(Account);
}
else
sb.Append("Win32 Error: " + Marshal.GetLastWin32Error());
return sb.ToString();
}
}

Hope this helps.

Willy.
Nov 15 '05 #9
"Willy Denoyette [MVP]" ...

- [2] uses the WTS API's which has not
the same prblems as [1], but requires
XP or higher.


Excellent!!!

It works like a charm!

Thank you very, very much!

// Bjorn A
Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Dave Benjamin | last post by:
Hey good people, I've been doing a lot of simultaneous Jython and CPython programming lately, and just wanted to say, with no intended ill will toward any of the individuals who have been...
6
by: V | last post by:
I have found that when I have a composite control that uses the CreateChildControls method, on a regular page load, Page_Load executes before CreateChildControls, but on a postback it is the...
3
by: Szymon Madejczyk | last post by:
example code: public class envtest { public static void Main() { System.Diagnostics.Process proc = System.Diagnostics.Process.GetCurrentProcess(); string env =...
5
by: Wysiwyg | last post by:
I'm new to c# programming and can't figure out how to avoid duplicating common code in multiple classes when I'm restricted to using different system base classes.. I'm using c# in asp.net to write...
3
by: jralford | last post by:
Hi, I have a main form with a number of controls on it. They are a range of different customized controls. There are some properties that belong to all of these controls, such as XOffset,...
2
by: XxLicherxX | last post by:
Hello everyone, Can someone tell me what this does and how I can use it? I can't seem to find any good examples online. Thanks
0
by: debnath1981 | last post by:
1. How to show all data (All coloum and all row) from a MS-Access Database table in Rich Text Box Just like a Crystall Report/Datagride view (Using MS-Access Database) 2.Complete code for...
4
by: ceh | last post by:
Hi, I'm using c# vs 2005 win xp pro sp2. I create a cmd prompt with pInvoke via CreateProcessWithLogonW Taskmgr shows that cmd instance running as that user. I type set in that cmd window and it...
6
by: ajk | last post by:
Hi I was wondering how to show different properties in design and run-mode for a user control? Is it possible to do this when implementing the System.ComponentModel.ICustomTypeDescriptor...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.