在Windows登录屏幕之前运行进程

时间:2013-10-21 18:39:12

标签: c# windows windows-services pinvoke

我尝试在显示Windows(7和xp)登录屏幕之前(或确切地说)时运行clac.exe进程。

我尝试了gpedit.msc方法(将calc.exe添加到Startup),onLogin/onLogout仅适用。

然后我创建了一个新的Windows服务,

代码(我的大部分代码来自:Running a Form in Windows Logon Screen C#):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Runtime.InteropServices;

namespace WindowsService2
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }
        [DllImport("Kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int WTSGetActiveConsoleSessionId();

        [DllImport("wtsapi32.dll", SetLastError = true)]
        static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private extern static bool DuplicateTokenEx(
            IntPtr hExistingToken,
            uint dwDesiredAccess,
            ref SECURITY_ATTRIBUTES lpTokenAttributes,
            SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
            TOKEN_TYPE TokenType,
            out IntPtr phNewToken);

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CreateProcessAsUser(
            IntPtr hToken,
            string lpApplicationName,
            string lpCommandLine,
            ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes,
            bool bInheritHandles,
            uint dwCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation);     
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool AdjustTokenPrivileges(IntPtr tokenhandle,
                                 [MarshalAs(UnmanagedType.Bool)] bool disableAllPrivileges,
                                 [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES newstate,
                                 uint bufferlength, IntPtr previousState, IntPtr returnlength);
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle,
            UInt32 DesiredAccess, out IntPtr TokenHandle);
        public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
        public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
        public const UInt32 TOKEN_DUPLICATE = 0x0002;
        public const UInt32 TOKEN_IMPERSONATE = 0x0004;
        public const UInt32 TOKEN_QUERY = 0x0008;
        public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
        public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
        public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
        public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
        public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
        public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
        public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
            TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
            TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
            TOKEN_ADJUST_SESSIONID);
        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int nLength;
            public IntPtr lpSecurityDescriptor;
            public int bInheritHandle;
        }
        enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_PRIVILEGES
        {
            public UInt32 PrivilegeCount;
            public LUID Luid;
            public UInt32 Attributes;
            public LUID_AND_ATTRIBUTES[] Privileges;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public uint LowPart;
            public int HighPart;
        }
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool LookupPrivilegeValue(string lpSystemName, string lpName,
            out LUID lpLuid);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        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 dwYSize;
            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)]
        internal struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }
[Flags]
    enum CreateProcessFlags : uint
    {
        DEBUG_PROCESS = 0x00000001,
        DEBUG_ONLY_THIS_PROCESS = 0x00000002,
        CREATE_SUSPENDED = 0x00000004,
        DETACHED_PROCESS = 0x00000008,
        CREATE_NEW_CONSOLE = 0x00000010,
        NORMAL_PRIORITY_CLASS = 0x00000020,
        IDLE_PRIORITY_CLASS = 0x00000040,
        HIGH_PRIORITY_CLASS = 0x00000080,
        REALTIME_PRIORITY_CLASS = 0x00000100,
        CREATE_NEW_PROCESS_GROUP = 0x00000200,
        CREATE_UNICODE_ENVIRONMENT = 0x00000400,
        CREATE_SEPARATE_WOW_VDM = 0x00000800,
        CREATE_SHARED_WOW_VDM = 0x00001000,
        CREATE_FORCEDOS = 0x00002000,
        BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
        ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
        INHERIT_PARENT_AFFINITY = 0x00010000,
        INHERIT_CALLER_PRIORITY = 0x00020000,
        CREATE_PROTECTED_PROCESS = 0x00040000,
        EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
        PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000,
        PROCESS_MODE_BACKGROUND_END = 0x00200000,
        CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
        CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
        CREATE_DEFAULT_ERROR_MODE = 0x04000000,
        CREATE_NO_WINDOW = 0x08000000,
        PROFILE_USER = 0x10000000,
        PROFILE_KERNEL = 0x20000000,
        PROFILE_SERVER = 0x40000000,
        CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000,
    }

        [StructLayout(LayoutKind.Sequential)]
        public struct LUID_AND_ATTRIBUTES
        {
            public LUID Luid;
            public UInt32 Attributes;
        }

        public class RunProcess
        {
            public void log(string error)
            {
                throw new Exception(error);
            }
            public void StartProcess(string pathOrName)
            {
                Process winLogon = null;
                foreach (Process p in Process.GetProcesses())
                {
                    if (p.ProcessName.Contains("winlogon"))
                    {
                        winLogon = p;
                        break;
                    }
                }
                // grab the winlogon's token
                IntPtr userToken = IntPtr.Zero;
                if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, out userToken))
                {
                    log("ERROR: OpenProcessToken returned false - " + Marshal.GetLastWin32Error());
                }
                WTSQueryUserToken((uint)WTSGetActiveConsoleSessionId(), out userToken);
                // create a new token
                IntPtr newToken = IntPtr.Zero;
                SECURITY_ATTRIBUTES tokenAttributes = new SECURITY_ATTRIBUTES();
                tokenAttributes.nLength = Marshal.SizeOf(tokenAttributes);
                SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
                threadAttributes.nLength = Marshal.SizeOf(threadAttributes);
                // duplicate the winlogon token to the new token
                if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                    TOKEN_TYPE.TokenImpersonation, out newToken))
                {
                    log("ERROR: DuplicateTokenEx returned false - " + Marshal.GetLastWin32Error());
                }

                TOKEN_PRIVILEGES tokPrivs = new TOKEN_PRIVILEGES();
                tokPrivs.PrivilegeCount = 1;
                LUID seDebugNameValue = new LUID();
                if (!LookupPrivilegeValue(null, "SeDebugPrivilege", out seDebugNameValue))
                {
                    log("ERROR: LookupPrivilegeValue returned false - " + Marshal.GetLastWin32Error());
                }

                tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
                tokPrivs.Privileges[0].Luid = seDebugNameValue;
                tokPrivs.Privileges[0].Attributes = 0x00000002;
                if (!AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero))
                {
                    log("ERROR: AdjustTokenPrivileges returned false - " + Marshal.GetLastWin32Error());
                }
                PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
                STARTUPINFO si = new STARTUPINFO();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "Winsta0\\Winlogon";

                // start the process using the new token
                 if (!CreateProcessAsUser(newToken, "calc.exe", null, ref tokenAttributes, ref threadAttributes,true, (uint)CreateProcessFlags.CREATE_NEW_CONSOLE | (uint)CreateProcessFlags.INHERIT_CALLER_PRIORITY, IntPtr.Zero,"C:\\Windows\\System32", ref si, out pi))
                {
                    log("ERROR: CreateProcessAsUser returned false - " + Marshal.GetLastWin32Error());
                }

                Process _p = Process.GetProcessById(pi.dwProcessId);
                if (_p != null)
                {
                    log("Process " + _p.Id + " Name " + _p.ProcessName);
                }
                else
                {
                    log("Not Found");
                }
            }
      }           
        RunProcess r = new RunProcess();
        protected override void OnStart(string[] args)
        {
            r.StartProcess("calc.exe");
        }

        protected override void OnStop()
        {
            r.log("Stoped");
        }
    }
}

我通过以下行安装了服务:

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe" "c:\myservice.exe"

现在我重新开始了。

然后我检查了登录屏幕显示时是否正在运行的进程,然后我发现没有计算器窗口,并且没有运行名为calc的进程。

然后我看到“WindowsService2”未运行(在taskmgr上)。

所以我认为它可以修复(我不会放弃这么快,我今天必须完成它),问题是:

为什么它不起作用,我现在需要做些什么来检查它为什么不起作用?

我更喜欢:

在登录屏幕(XP和Windows 7)之前还有其他方式(或方法)运行进程吗?

(好的答案是很好的例子加上好的解释):)

修改
解决方案是安装,
安装日志:

Installing assembly 'c:\WindowsService2.exe'.
Affected parameters are:
   logtoconsole = 
   logfile = c:\WindowsService2.InstallLog
   assemblypath = c:\WindowsService2.exe
No public installers with the RunInstallerAttribute.Yes attribute could be found in the c:\WindowsService2.exe assembly.
Committing assembly 'c:\WindowsService2.exe'.
Affected parameters are:
   logtoconsole = 
   logfile = c:\WindowsService2.InstallLog
   assemblypath = c:\WindowsService2.exe
No public installers with the RunInstallerAttribute.Yes attribute could be found in the c:\WindowsService2.exe assembly.
Remove InstallState file because there are no installers.


无法安装,因为:

No public installers with the RunInstallerAttribute.Yes attribute could be found in the c:\WindowsService2.exe assembly.


我现在应该怎么做? :S
(我试过public static readonly RunInstallerAttribute Yes;,我甚至尝试以管理员身份运行cmd.exe

1 个答案:

答案 0 :(得分:-1)

在启动之前启动应用程序有三个选项:

您可以使用mscorlib.dll(RegistryKey类)函数和类添加新的注册表值:

RegistryKey add = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
add.SetValue("Your App Name", "\"" + Application.ExecutablePath.ToString() + "\"");


其他地点:

HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices
HKLM\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnceEx 

您可以手动添加应用程序:

gpedit.msc->windows settings->script files(startup/shutdown)->startup->add..(choose youre application assembly file)

(所有gpedit值都保存在注册表中,您也可以使用GPMGMTLib添加应用程序组装路径(以使应用程序更方便)。

您可以将应用程序组件文件移动或复制到:

Environment.GetFolderPath(Environment.SpecialFolder.Startup)