[C#.Net]Window服务调用外部程序
最近遇到要做回传服务内增加开关,可以自定义运行一些脚本已方便收集PC状态,发现Bat始终无法运行,上网找了半天才发现和Session0有关,也就是程序有不同级别的访问权限,Vista以上版本为了安全因素,限制了不同Session间的访问,可以使用Windows API还直接穿透Session0,也就是获得最高权限
相关类如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text; namespace IctInfo
{
/// <summary>
/// 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
/// </summary>
public class Interop
{
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; public static void ShowMessageBox(string message, string title)
{
int resp = ;
WTSSendMessage(
WTS_CURRENT_SERVER_HANDLE,
WTSGetActiveConsoleSessionId(),
title, title.Length,
message, message.Length,
, , out resp, false);
} [DllImport("kernel32.dll", SetLastError = true)]
public static extern int WTSGetActiveConsoleSessionId(); [DllImport("wtsapi32.dll", SetLastError = true)]
public static extern bool WTSSendMessage(
IntPtr hServer,
int SessionId,
String pTitle,
int TitleLength,
String pMessage,
int MessageLength,
int Style,
int Timeout,
out int pResponse,
bool bWait);
//在ShowMessageBox 函数中调用了WTSSendMessage 来发送信息窗口,这样我们就可以在Service 的OnStart 函数中使用,打开Service1.cs 加入下面代码:
public static void CreateProcess(string app, string path)
{
bool result;
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero; PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa); STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si); int dwSessionID = WTSGetActiveConsoleSessionId();
result = WTSQueryUserToken(dwSessionID, out hToken); if (!result)
{
ShowMessageBox("WTSQueryUserToken failed", "AlertService Message");
} result = DuplicateTokenEx(
hToken,
GENERIC_ALL_ACCESS,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref hDupedToken
); if (!result)
{
ShowMessageBox("DuplicateTokenEx failed", "AlertService Message");
} IntPtr lpEnvironment = IntPtr.Zero;
result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false); if (!result)
{
ShowMessageBox("CreateEnvironmentBlock failed", "AlertService Message");
} result = CreateProcessAsUser(
hDupedToken,
app,
String.Empty,
ref sa, ref sa,
false, , IntPtr.Zero,
path, ref si, ref pi); if (!result)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
ShowMessageBox(message, "AlertService Message");
} if (pi.hProcess != IntPtr.Zero)
CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
CloseHandle(hDupedToken);
} [StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
} [StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessID;
public Int32 dwThreadID;
} [StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public Int32 Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
} public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
} public enum TOKEN_TYPE
{
TokenPrimary = ,
TokenImpersonation
} public const int GENERIC_ALL_ACCESS = 0x10000000; [DllImport("kernel32.dll", SetLastError = true,
CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool CloseHandle(IntPtr handle); [DllImport("advapi32.dll", SetLastError = true,
CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandle,
Int32 dwCreationFlags,
IntPtr lpEnvrionment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation); [DllImport("advapi32.dll", SetLastError = true)]
public static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
Int32 dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken); [DllImport("wtsapi32.dll", SetLastError = true)]
public static extern bool WTSQueryUserToken(
Int32 sessionId,
out IntPtr Token); [DllImport("userenv.dll", SetLastError = true)]
static extern bool CreateEnvironmentBlock(
out IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit); }
}
特别感谢以下大牛的技术分享
解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
[C#.Net]Window服务调用外部程序的更多相关文章
- window服务session隔离
在window服务中抓取窗体是做不到的,因为window系统的session隔离机制:如果想要调用外部程序,可以通过 创建代理进程 进行操作(通过非托管代码CreateProcessAsUser函数进 ...
- C#编写window服务,一步一步(1)
Window服务是啥,这里就不废话了,如何用在哪里用也不废话了,这里我这篇文章只是详述了我在vs2012中创建window服务的经过,希望对你有所帮助. 另外:我在编写服务过程中参考了 Profess ...
- C# 编写Window服务基础(一)
一.Windows服务介绍: Windows服务以前被称作NT服务,是一些运行在Windows NT.Windows 2000和Windows XP等操作系统下用户环境以外的程序.在以前,编写Wind ...
- C# 编写短信发送Window服务
我们做项目过程中,一般都会有发送短信的需求.最常见的就是户注册或者登录时发送短信验证码.不同类型的短信发送,我们都可以放到到一张短信表中,然后通过一个定时的作业去执行短信发送.而定时作业的执行,我们就 ...
- C# 客户端程序调用外部程序的三种实现
简介 我们用C#来开发客户端程序的时候,总会不可避免的需要调用外部程序或者访问网站,本篇博客介绍了三种调用外部应用的方法,供参考 实现 第一种是利用shell32.dll,实现ShellExecute ...
- 【权限维持】window服务端常见后门技术
0x00 前言 未知攻焉知防,攻击者在获取服务器权限后,通常会用一些后门技术来维持服务器权限,服务器一旦被植入后门,攻击者如入无人之境.这里整理一些window服务端常见的后门技术,了解攻击者的常见后 ...
- C#写的window服务内存溢出
浅谈c#垃圾回收机制(GC) 写了一个window服务,循环更新sqlite记录,内存一点点稳步增长.三天后,内存溢出.于是,我从自己的代码入手,查找到底哪儿占用内存释放不掉,最终明确是调用servi ...
- 接Window服务(二)
接Window服务(一) ServiceController方法调用 1 public partial class Service1 : ServiceBase 2 { 3 public Servic ...
- window 服务(一)
windows服务应用程序是一种长期运行在操作系统后台的程序,它对于服务器环境特别适合,它没有用户界面,不会产生任何可视输出,任何用户输出都回被写进windows事件日志.计算机启动时,服务会自动开始 ...
随机推荐
- PHP:自己写的mysql操作类
a{ font-weight: bold; display: block; text-align: center; color: #5887bf; font-size: 22px; } .conten ...
- js 字符串截取函数substr,substring,slice之间的差异
js 字符串的截取,主要有三个函数,一般使用三个函数:substr,substring,slice. 而这三个函数是不完全一样的,平时很难记住,在这里做下笔记,下次遇到的时候,直接从这里参考,调用合适 ...
- ensureCapacity增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
扩容原则: 若参数值大于底层数组长度的1.5倍,则数组的长度就扩容为这个参数值:若小于底层数组长度的1.5倍,则数组长度就扩容为底层数组长度的1.5倍. ensureCapacity提高效率 fina ...
- LevelDB源码分析-Version
Version VersionSet类 VersionSet管理整个LevelDB的当前状态: class VersionSet { public: // ... // Apply *edit to ...
- SSM商城项目(十一)
1. 学习计划 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 Ajax跨域请求(jsonp) 2. Sso系统工程搭建 需要创建一个sso服务工程,可以参考e ...
- github 绑定域名
github的域名其实就两种,一种是个人主页,即所谓的每个账号只有一个的个人主页,XXXX.github.io,分支是master: 另一种是项目主页,可以有无数个,网上说分支应该是gh-pages, ...
- gitlab-ci.xml:script config should be a string or an array of strings
The following command in a job script: STATUS_ID=$(grep -Eo "Status Code [0-9]+: Done" som ...
- 2019-04(1)(Python学习)
9.1 迭代器 创建迭代器的3种方法: 方法一: 容器对象添加 __iter__() 和 __next__() 方法(Python 2.7 中是 next()):__iter__() 返回迭代器对象本 ...
- 大数据下基于Tensorflow框架的深度学习示例教程
近几年,信息时代的快速发展产生了海量数据,诞生了无数前沿的大数据技术与应用.在当今大数据时代的产业界,商业决策日益基于数据的分析作出.当数据膨胀到一定规模时,基于机器学习对海量复杂数据的分析更能产生较 ...
- 【python路飞】编码 ascii码(256位 =1个字节)美国;unicode(万国码)中文 一共9万个 用4个字节表示这9万个子 17位就能表示
8位一个字节 1024字节 1KB 1024KB 1MB ASCII码不能包含中文.创建了unicode,一个中文4个字节.UTF-8一个中文3个.GBK中国人用的只包含中文2个字节 升级 Un ...