解决方案 »

  1.   

    对,因为windows服务在单独的账户中运行,和当前桌面登录的账户两不干涉。甚至,只要电脑开机,没有用户登录,服务都可以运行。
      

  2.   

    楼主没有明白windows系统多用户的特性,好比两个人同时在一台电脑上操作,各有各的桌面,一个人开户的winform,是不会显示到另一个人的桌面上的.
      

  3.   

    那要看你想要什么效果了.
    如果不涉及到对当前登录用户操作,那么效果一样这些操作包括:显示主窗体及弹出窗体(包括messagebox),修改用户桌面及桌面背景图片,设置屏幕保护,电源选项等.
      

  4.   

    那要看你想要什么效果了.
    如果不涉及到对当前登录用户操作,那么效果一样这些操作包括:显示主窗体及弹出窗体(包括messagebox),修改用户桌面及桌面背景图片,设置屏幕保护,电源选项等.是不是没有弹出窗体,程序也是照样运行的是吧
      

  5.   

    那要看你想要什么效果了.
    如果不涉及到对当前登录用户操作,那么效果一样这些操作包括:显示主窗体及弹出窗体(包括messagebox),修改用户桌面及桌面背景图片,设置屏幕保护,电源选项等.是不是没有弹出窗体,程序也是照样运行的是吧
    你可以做个定时写入日志的功能,不就能知道程序是不是在正常运行了么.
      

  6.   

    服务本身就是没有窗口的,你用ProcessStart启动的进程,默认是以服务进程的会话令牌开启的,自然也是没有窗口的
    给你一个兼容XP/Win7/Win8/2008的吧需要注意的是,在Win8的Session隔离下,使用API   WTSGetConsoleSessionId()获取的不一定是活动用户的sessionID了
    要通过枚举找出来,其中跟踪日志的方法自己改掉使用方法
    int? sessonId = GetActiveSessionId();
    //如果已有用户登陆(
    if(sessionId.HasValue)
    {
            CreateProcess(sessionid, exe完整路径, 启动参数);
    }
    //sessionId是用户的会话ID,默认为当前活动用户;appFullName是程序完整路径,args是启动参数
    public static bool CreateProcess(int sessionId, string appFullName, string args)
            {
                if (!System.IO.File.Exists(appFullName))
                {
                    throw new System.IO.FileNotFoundException(appFullName);
                }
                bool sucess = false;
                IntPtr hToken = IntPtr.Zero,
                       hDupedToken = IntPtr.Zero,
                       lpEnvironment = IntPtr.Zero;
                Mapper.Process_Information pi = new Mapper.Process_Information();
                Mapper.SecurityAttributes sa;
                try
                {
                    //获取指定会话的用户令牌,须具备System权限
                    sucess = Mapper.WTSQueryUserToken(sessionId, out hToken);
                    if(!sucess)
                    {
                        //服务程序中,获取指定会话的桌面进程
                        var explorer = Process.GetProcesses()
                            .FirstOrDefault(p => p.SessionId == sessionId && string.Equals(p.ProcessName, Setting.ExplorerProcess, StringComparison.OrdinalIgnoreCase));
                        if (explorer == null)
                        {
                            return false;
                        }
                        sucess = Mapper.OpenProcessToken(explorer.Handle, TokenAccessLevels.AllAccess, ref hToken);
                        if (!sucess)
                        {
                            TraceWin32Error("CreateProcessAs Session" + sessionId.ToString(), "WTSQueryUserToken");
                            return false;
                        }
                    }
                    //复制桌面进程的句柄
                    sa = new Mapper.SecurityAttributes();
                    sa.Length = Marshal.SizeOf(sa);
                    var si = new Mapper.StartUpInfo();
                    si.cb = Marshal.SizeOf(si);
                    sucess = Mapper.DuplicateTokenEx(
                          hToken,
                          Mapper.GENERIC_ALL_ACCESS,
                          ref sa,
                          (int)Mapper.SecurityImpersonationLevel.SecurityIdentification,
                          (int)Mapper.TokenType.TokenPrimary,
                          ref hDupedToken
                    );
                    if (!sucess)
                    {
                        TraceWin32Error("CreateProcessAs Session" + sessionId.ToString(), "DuplicateTokenEx");
                        return false;
                    }
                    //利用复制的句柄在指定的会话中初始化运行环境                
                    sucess = Mapper.CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);
                    if (!sucess)
                    {
                        TraceWin32Error("CreateProcessAs Session" + sessionId.ToString(), "CreateEnvironmentBlock");
                        return false;
                    }
                    //在指定会话中开启进程
                    if (!string.IsNullOrEmpty(args))
                    {
                        args = string.Format("\"{0}\" {1}", appFullName, args);
                        appFullName = null;
                    }
                    sucess = Mapper.CreateProcessAsUser(
                        hDupedToken,
                        appFullName,
                        args,
                        ref sa, ref sa,
                        false, 0, IntPtr.Zero,
                        null,
                        ref si,
                        ref pi
                    );
                    if (!sucess)
                    {
                        TraceWin32Error("CreateProcessAs Session" + sessionId.ToString(), "CreateProcessAsUser");
                    }
                    return sucess;
                }
                catch (Exception exp)
                {
                    TraceWin32Error("CreateProcessAs Session" + sessionId.ToString(), exp.Message);
                    return false;
                }
                finally
                {
                    if (hDupedToken != IntPtr.Zero) Mapper.CloseHandle(hDupedToken);
                    if (lpEnvironment != IntPtr.Zero) Mapper.DestroyEnvironmentBlock(lpEnvironment);
                    if (pi.hProcess != Mapper.INVALID_HANDLE_VALUE) Mapper.CloseHandle(pi.hProcess);
                    if (pi.hThread  != Mapper.INVALID_HANDLE_VALUE) Mapper.CloseHandle(pi.hThread);
                } public static int? GetActiveSessionId()
            {
                IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero, ppSessionInfo = IntPtr.Zero;
                List<string> result = new List<string>();
                try
                {
                    int count = 0;
                    bool success = Mapper.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref ppSessionInfo, ref count);
                    if (success)
                    {
                        int dataSize = Marshal.SizeOf(typeof(Mapper.WTS_SESSION_INFO));
                        var current = ppSessionInfo.ToInt64();  //数组起始地址
                        for (int i = 0; i < count; i++)
                        {
                            var si = (Mapper.WTS_SESSION_INFO)Marshal.PtrToStructure((IntPtr)current, typeof(Mapper.WTS_SESSION_INFO));
                            if (si.State == Mapper.WTS_CONNECTSTATE_CLASS.WTSActive)
                            {
                                return si.SessionID;
                            }
                            current += dataSize;
                        }
                    }
                    else
                    {
                        TraceWin32Error("GetActiveSessionId", "WTSEnumerateSessions");                    
                    }
                    return null;
                }
                finally
                {
                    if (ppSessionInfo != IntPtr.Zero) Mapper.WTSFreeMemory(ppSessionInfo);
                }
            }
      

  7.   

    int? sessonId = GetActiveSessionId();
    //如果已有用户登陆(
    if(sessionId.HasValue)
    {
            CreateProcess(sessionid.Value, exe完整路径, 启动参数);
    }
     #region API声明
    [DllImport("wtsapi32.dll", SetLastError = true)]
            public static extern bool WTSEnumerateSessions(
                IntPtr hServer,
                [MarshalAs(UnmanagedType.U4)] uint Reserved,
                [MarshalAs(UnmanagedType.U4)] uint Version,
                ref IntPtr ppSessionInfo,
                [MarshalAs(UnmanagedType.U4)] ref Int32 pCount);        [StructLayout(LayoutKind.Sequential)]
            public struct WTS_SESSION_INFO
            {
                public Int32 SessionID;            [MarshalAs(UnmanagedType.LPStr)]
                public String pWinStationName;            public WTS_CONNECTSTATE_CLASS State;
            }        public enum WTS_CONNECTSTATE_CLASS
            {
                WTSActive,
                WTSConnected,
                WTSConnectQuery,
                WTSShadow,
                WTSDisconnected,
                WTSIdle,
                WTSListen,
                WTSReset,
                WTSDown,
                WTSInit
            }        [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 SecurityAttributes
            {
                public Int32 Length;
                public IntPtr lpSecurityDescriptor;
                public bool bInheritHandle;
            }        public enum SecurityImpersonationLevel
            {
                SecurityAnonymous,
                SecurityIdentification,
                SecurityImpersonation,
                SecurityDelegation
            }        public enum TokenType
            {
                TokenPrimary = 1,
                TokenImpersonation
            }        [DllImport("advapi32.dll", SetLastError = true)]
            public static extern bool DuplicateTokenEx(
                IntPtr hExistingToken,
                Int32 dwDesiredAccess,
                ref SecurityAttributes lpThreadAttributes,
                Int32 ImpersonationLevel,
                Int32 dwTokenType,
                ref IntPtr phNewToken);                [DllImport("userenv.dll", SetLastError = true)]
            public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);        [DllImport("userenv.dll", SetLastError = true)]
            public static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);        [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool CreateProcessAsUser(
                IntPtr hToken,
                string lpApplicationName,
                string lpCommandLine,
                ref SecurityAttributes lpProcessAttributes,
                ref SecurityAttributes lpThreadAttributes,
                bool bInheritHandle,
                Int32 dwCreationFlags,
                IntPtr lpEnvrionment,
                string lpCurrentDirectory,
                ref StartUpInfo lpStartupInfo,
                ref Process_Information lpProcessInformation);
        
            //以下定义同System.Windows.Forms.SecurityIDType
            public enum SID_NAME_USE
            {
                User = 1,
                Group,
                Domain,
                Alias,
                WellKnownGroup,
                Account,
                Invalid,
                Unknown,
                Computer,
                Label
            }        [StructLayout(LayoutKind.Sequential)]
            public struct TOKEN_USER
            {
                public SID_AND_ATTRIBUTES User;
            }        [StructLayout(LayoutKind.Sequential)]
            public struct SID_AND_ATTRIBUTES
            {
                public IntPtr Sid;
                public uint Attributes;
            }        /// <summary>
            /// 获取控制台当前活动的会话ID,若没有将返回0xFFFFFFFF(在远程连接至Server2008或Win8时取得的值并不是用户的会话ID)
            /// </summary>
            /// <returns></returns>
            //[DllImport("kernel32.dll", SetLastError = true)]
            //public static extern uint WTSGetActiveConsoleSessionId();        /// <summary>
            /// 查询指定会话ID的用户令牌,调用方必须具备System权限
            /// </summary>
            [DllImport("wtsapi32.dll", SetLastError = true)]
            public static extern bool WTSQueryUserToken(int sessionId, out IntPtr Token);        [DllImport("advapi32", SetLastError = true)]
            public static extern bool OpenProcessToken(IntPtr processHandle, TokenAccessLevels desiredAccess, ref IntPtr htok);        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetTokenInformation(IntPtr htok, uint tokenInformationClass, IntPtr hTokInformation, uint tokenInformationLength, out uint returnLength);        #endregion
      

  8.   

    我这个根本就不需要登陆的,只要程序能够正常运行就可以了,界面也没有任何东西的。本来打算做成服务的,但是考虑到服务不好更新所以才做成winform