I’m querying printers via csharp/.net inside a WCF service. When called locally (i.e. a client run from the local machine) It returns one set of printers. When called remotely, it calls a different set.
The wcf service is setup to accept and impersonate using the credentials passed in the creation of the client.
The major difference I’ve notice via remote debugging is the Authentication Type in the call to:
WindowsIdentity.GetCurrent()
Which is Kerberos when called remotely and Neogotiate when called locally.
Here is a quick sampling of code:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public List<string> GetAvailablePrinters()
{
List<string> retval = new List<string>();
using (ManagementClass printerClass = new ManagementClass("win32_printer"))
{
ManagementObjectCollection printers = printerClass.GetInstances();
foreach (ManagementObject printer in printers)
{
if ((bool)printer["Shared"] == true)
retval.Add((string)printer["Name"]);
}
}
return retval;
}
Both calls are succeeding, however I get the correct list locally, and nothing remotely.
Here is a side by side of the two:
Test Executable run on the local server:
{System.Security.Principal.WindowsIdentity}
AuthenticationType: "Negotiate"
Groups: {System.Security.Principal.IdentityReferenceCollection}
ImpersonationLevel: Impersonation
IsAnonymous: false
IsAuthenticated: true
IsGuest: false
IsSystem: false
m_authType: null
m_groups: {System.Security.Principal.IdentityReferenceCollection}
m_impersonationLevel: Impersonation
m_isAuthenticated: 1
m_name: null
m_owner: null
m_safeTokenHandle: {Microsoft.Win32.SafeHandles.SafeTokenHandle}
m_user: {xxxxx}
Name: "adomain\\auser"
Owner: {xxxxx}
Token: token number
TokenHandle: {Microsoft.Win32.SafeHandles.SafeTokenHandle}
User: {xxxxxxxx}
Same executable run remotely
{System.Security.Principal.WindowsIdentity}
AuthenticationType: "Kerberos"
Groups: {System.Security.Principal.IdentityReferenceCollection}
ImpersonationLevel: Impersonation
IsAnonymous: false
IsAuthenticated: true
IsGuest: false
IsSystem: false
m_authType: null
m_groups: {System.Security.Principal.IdentityReferenceCollection}
m_impersonationLevel: Impersonation
m_isAuthenticated: 1
m_name: null
m_owner: null
m_safeTokenHandle: {Microsoft.Win32.SafeHandles.SafeTokenHandle}
m_user: {xxxxx}
Name: "adomain\\auser"
Owner: {differnt owner}
Token: different Token number
TokenHandle: {Microsoft.Win32.SafeHandles.SafeTokenHandle}
User: {xxxxxx}
It seems that the printers you are trying to list are remote printers to the machine running the WCF service. Impersonation only lets you access local resources available on the machine being called. This good MSDN article on impersonation and delegation in WCF should get you going on the right track. You’ll either need to implement delegation to list remote resources from the WCF service or not use delegation at all and make the WCF service run under a domain account that can list the remote printers.