Pergunta

Eu escrevi um pequeno serviço (Win32 simples) e gostaria de saber se é possível executar várias instâncias dele quando vários usuários estão conectados.

Basicamente, digamos que temos UserA e UserB para UserA, o serviço faria logon como "domínio\UserA" e para UserB o serviço faria logon como "domínio\UserB" - isso é do mesmo executável, é claro.Posso alterar o logon dinamicamente usando a função ChangeServiceConfig(), mas parece que isso muda em todo o sistema, embora eu gostaria que cada usuário tivesse sua própria cópia do serviço em execução apenas para ele.

Agradecemos antecipadamente por qualquer indicação.

Foi útil?

Solução

Os serviços Win32 são projetados para serem em todo grupo.

Outras dicas

Talvez seja possível que o serviço crie processos filhos que adotem as credenciais do usuário (ou sejam iniciadas com elas)? Dessa forma, você ainda está limitado a uma única instância do serviço, mas é capaz de fazer seus trabalhos por usuário da mesma forma. IIRC O Serviço de Agendador de Tarefas do Windows faz isso.

Todo o conceito de serviço é que ele é iniciado antes que qualquer usuário esteja conectado. Portanto, mesmo que isso fosse possível, você não seria capaz de escolher entre USERA e UserB quando o serviço começar porque nenhum deles ainda está conectado.


Uma direção possível seria para o serviço ser executado como sistema e a cada poucos minutos verificar se houver um usuário conectado, se houver- se passar por esse usuário e fazer essas coisas.

Sim, isso parece perto (estou respondendo comentários de Greg, mas os comentários são muito curtos para se encaixar na minha resposta).

Não conheço a lista de usuários de antemão, mas há um aplicativo de controle da GUI que seria usado para inserir pares de nome de usuário/senha para cada usuário. Portanto, a USERA faz logon, executou o aplicativo, inseria suas credenciais e serviços usaria isso. Ao mesmo tempo (depois que a USERA foi efetuada, mas o serviço ainda está em execução com as credenciais da USERA) o userb loga, usa o aplicativo e outra cópia do serviço começa a ser executada como userb. Assim, ao mesmo tempo, os serviços Usera e UserB estão em execução.

Isso é possível?

Você provavelmente está procurando se passar pelos usuários. Confira algumas referências que encontrei com uma rápida pesquisa no Google aqui:

Parece que você realmente tem dois requisitos diferentes e conflitantes, quanto ao tempo e à identidade.

  1. Execute como cada usuário conectado ao usuário
  2. Execute automaticamente, mesmo que nenhum usuário esteja conectado.

Não há como fazer isso trivialmente, considere envolver seu programa em um serviço; O programa será executado normalmente na inicialização para cada usuário (através da pasta de inicialização ou TaskScheduler) e além do que, além do mais Crie um serviço para executar seu aplicativo como usuário do sistema (ou qualquer outro usuário que você definir).
Como você também precisa (você menciona isso nos comentários) o aplicativo para continuar funcionando como o enduser, mesmo depois que ele se apodrece, você pode gerenciar esse processo para você.

No entanto, essa pode não ser a melhor idéia, já que o usuário ainda está efetivamente conectado. Isso pode ter inúmeros efeitos colaterais, incluindo segurança, desempenho (muitos usuários conectados de uma só vez ...), etc.

Você pode criar um aplicativo de serviço e um aplicativo sem serviço (normal) e fazê-los se comunicar através do IPC (arquivo mapeado, tubos, correio ... você escolhe).

Dessa forma, você resolve todos os problemas.

Nota: O mesmo aplicativo pode se comportar de maneira diferente - quando iniciado como um processo e quando iniciado por um usuário, mas no final é a mesma coisa, você ainda tem 2 aplicativos (não importa se você tem apenas um executável).

É possível executar contas diferentes. De fato, isso é comum. Veja svchost.exe, que implementa vários serviços do sistema operacional.

Só não entendo como você determina quais contas. Em uma grande empresa, muitos PCs são configurados para que todos os 100.000 funcionários possam usá -lo. Você não deseja executar seu serviço como usuários conectados, nem pode executá-lo para todos os 100.000 usuários. Então, para quais contas, tenho que perguntar?

Um processo do Windows só pode ser executado com os privilégios de um único usuário por vez.Isso se aplica a serviços e outros processos.Com privilégios suficientes é possível “alternar” entre diferentes usuários usando representação.O padrão mais comum para o que você está tentando fazer é ter uma instância de um serviço privilegiado que se registra para efetuar login/logout de eventos e cria processos filhos de acordo, cada um deles representando o usuário conectado.O padrão também simplificará a UI à medida que cada processo for executado na área de trabalho de cada usuário separado, como se fosse um aplicativo normal.

Se você mantiver o código do serviço privilegiado o mais simples possível, esse padrão terá o benefício adicional de minimizar a superfície de ataque do seu código.Se um usuário encontrar um problema de segurança no lado "executando como usuário" do seu serviço, isso não será problema, enquanto problemas de segurança nos serviços privilegiados podem levar ao escalonamento de privilégios.Na verdade, antes dos serviços privilegiados do Vista implementarem um loop de processamento de mensagens do Windows, eles eram vulneráveis ​​a um tipo de ataque chamado Ataques de estilhaçamento, do qual você deve estar ciente, considerando o que está tentando fazer.

Você quer isso correndo o tempo todo, para que você queira um serviço.

Você deseja que algo rastreie cada usuário, para que você seja executado na sessão do usuário e se comunique com o Serviço (usando Pipes nomeados ou DCOM ou o que quer que se adapte aos seus requisitos).

Você não precisa de várias instâncias do seu serviço. A partir da descrição do seu problema, parece que o que você precisa é de um serviço que possa se passar por usuários e executar trabalhos em seu nome.

Você pode fazer isso implementando um objeto COM hospedado em um serviço. Seu aplicativo cliente (que o usuário final é executado) chamará o CocreateInstanceEx no seu CLSID. Isso faria com que uma nova instância do seu objeto COM fosse criada em seu serviço. Em seguida, o aplicativo pode usar um método em uma de suas interfaces para passar as credenciais de usuário coletadas para o objeto COM (embora eu tenha cuidado em coletar credenciais e, em vez disso, ver se consigo passar no token do usuário). O objeto COM que está sendo executado no contexto do serviço pode chamar logonUser () para fazer login no usuário e se passar, para que possa fazer o que quer que seja em seu nome (como encontrar a pasta AppData local :-)). Outras respostas têm bons links para personificar usuários usando credenciais ou token.

Se você se sentir confortável com o COM, sugiro que você crie seus objetos como multithread (morando no MTA), para que a execução deles não seja serializada por COM. Caso contrário, o modelo rosqueado padrão padrão seria bom o suficiente para você.

O assistente do Visual Studio ATL pode gerar o esqueleto de um objeto COM que vive em um serviço. Você também pode ler sobre a implementação do serviço Windows com o ATL aqui: http://msdn.microsoft.com/en-us/library/74y2334x(vs.80).aspx

Se você não conhece nada, pode usar outros canais de comunicação para passar as credenciais para o seu serviço.

De qualquer forma, uma vez que seu serviço obtém as credenciais, todo o trabalho em nome do usuário deverá ser executado em um encadeamento de segundo plano, para não bloquear o aplicativo em execução como usuário.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top