472,802 Members | 1,373 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,802 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 2412

"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...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

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.