Доступ к принтеру от олицетворенного пользователя в службе Windows - PullRequest
0 голосов
/ 12 апреля 2019

Я разрабатываю службу Windows для загрузки и печати документов (pdf, excel. Word) под разными учетными данными (необходимо добавить документ в очередь печати под разными пользователями). Когда я выдаю себя за пользователя, я получаю исключение «Настройки принтера недействительны». Когда я запускаю сервис в своем собственном контексте, исключений нет, и он работает как ожидалось

Вот конфигурация службы Windows:

var exitCode = HostFactory.Run(x =>
{
    x.Service<PrinterCentralPointService>(service =>
    {
        service.ConstructUsing(printerService => new PrinterCentralPointService());
        service.WhenStarted(printerService => printerService.Start());
        service.WhenStopped(printerService => printerService.Stop());
    });
    x.RunAsLocalSystem();
});
int exitCodeValue = (int)Convert.ChangeType(exitCode, exitCode.GetTypeCode());
Environment.ExitCode = exitCodeValue;

Услуги:

public class PrinterCentralPointService {
    private readonly Timer _timer;
    public PrinterCentralPointService() {
        _timer = new Timer(1000) { AutoReset = false };
        _timer.Elapsed += TimerElapsed;
    }
    private void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        var ps = new PrinterSettings(); // works fine
        using (var i = new ImpersonatedUser("login", "domain", "password"))
        {
            var ps = new PrinterSettings(); // default printer is not defined and etc...      // ... aspose code to send to printer
        }
    }
    public void Start() {
        _timer.Start();
    }
    public void Stop() {
        _timer.Stop();
    }
}

And ImpersonatedUser.cs

public class ImpersonatedUser: IDisposable 
{
    IntPtr userHandle;
    WindowsImpersonationContext impersonationContext;
    public ImpersonatedUser(string user, string domain, string password) 
    {
        userHandle = IntPtr.Zero;
        bool loggedOn = LogonUser(
            user,
            domain,
            password,
            LogonType.Batch,
            LogonProvider.Default,
            out userHandle);
        if (!loggedOn)
            throw new Win32Exception(Marshal.GetLastWin32Error());
        impersonationContext = WindowsIdentity.Impersonate(userHandle);
    }
    public void Dispose() 
    {
        if (userHandle != IntPtr.Zero) 
        {
            CloseHandle(userHandle);
            userHandle = IntPtr.Zero;
            impersonationContext.Undo();
            logger.Debug("Finished Impersonating user");
        }
    }
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        LogonType dwLogonType,
        LogonProvider dwLogonProvider,
        out IntPtr phToken
    );
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hHandle);
    enum LogonType: int 
    {
        Interactive = 2,
            Network = 3,
            Batch = 4,
            Service = 5,
            NetworkCleartext = 8,
            NewCredentials = 9,
    }
    enum LogonProvider: int 
    {
        Default = 0,
    }
}

Что я делаю не так?

...