问题:用注册表的开机自启发现有输入密码提示的界面要必须登录才能启动程序,若没有登录程序是不会运行。
解决方案:做一个windows服务启动这程序不管有没有密码提示的界面都不用担心程序不会运行。
在vs2010上新建一个windows服务,然后在service1.cs【设计】中右键-------选择添加安装程序显现的界面会如下图:
在projectInstaller.cs中写如下代码:
public ProjectInstaller()
{
InitializeComponent();
//AppDomain.CurrentDomain.SetupInformation.ApplicationBase 获取可执行文件的路径
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; //权限账户设置
this.serviceInstaller1.ServiceName =“服务名” ; //我的服务名称,这个名字你说了算
this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic; //服务自动运行
}
然后在添加一个win_Interop类:
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
/// <summary>
/// 服务程序执行消息提示,前台MessageBox.Show
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="title">标题</param>
public static void ShowServiceMessage(string message, string title)
{
int resp = 0;
WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId(), title, title.Length, message, message.Length, 0, 0, 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);
#region P/Invoke WTS APIs
private enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct WTS_SESSION_INFO
{
public UInt32 SessionID;
public string pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool WTSEnumerateSessions(
IntPtr hServer,
[MarshalAs(UnmanagedType.U4)] UInt32 Reserved,
[MarshalAs(UnmanagedType.U4)] UInt32 Version,
ref IntPtr ppSessionInfo,
[MarshalAs(UnmanagedType.U4)] ref UInt32 pSessionInfoCount
);
[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
static extern void WTSFreeMemory(IntPtr pMemory);
[DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
#endregion
#region P/Invoke CreateProcessAsUser
/// <summary>
/// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser.
/// </summary>
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
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, CharSet = CharSet.Auto)]
struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
/// <summary>
/// 以当前登录的windows用户(角色权限)运行指定程序进程
/// </summary>
/// <param name="hToken"></param>
/// <param name="lpApplicationName">指定程序(全路径)</param>
/// <param name="lpCommandLine">参数</param>
/// <param name="lpProcessAttributes">进程属性</param>
/// <param name="lpThreadAttributes">线程属性</param>
/// <param name="bInheritHandles"></param>
/// <param name="dwCreationFlags"></param>
/// <param name="lpEnvironment"></param>
/// <param name="lpCurrentDirectory"></param>
/// <param name="lpStartupInfo">程序启动属性</param>
/// <param name="lpProcessInformation">最后返回的进程信息</param>
/// <returns>是否调用成功</returns>
[DllImport("ADVAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CreateProcessAsUser(IntPtr hToken,string lpApplicationName,string lpCommandLine,IntPtr lpProcessAttributes,IntPtr lpThreadAttributes,
bool bInheritHandles,uint dwCreationFlags,string lpEnvironment,string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,out PROCESS_INFORMATION lpProcessInformation);
[DllImport("KERNEL32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CloseHandle(IntPtr hHandle);
#endregion
/// <summary>
/// 以当前登录系统的用户角色权限启动指定的进程
/// </summary>
/// <param name="ChildProcName">指定的进程(全路径)</param>
public static void CreateProcess(string ChildProcName)
{
IntPtr ppSessionInfo = IntPtr.Zero;
UInt32 SessionCount = 0;
if (WTSEnumerateSessions(
(IntPtr)WTS_CURRENT_SERVER_HANDLE, // Current RD Session Host Server handle would be zero.
0, // This reserved parameter must be zero.
1, // The version of the enumeration request must be 1.
ref ppSessionInfo, // This would point to an array of session info.
ref SessionCount // This would indicate the length of the above array.
))
{
for (int nCount = 0; nCount < SessionCount; nCount++)
{
WTS_SESSION_INFO tSessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure(ppSessionInfo + nCount * Marshal.SizeOf(typeof(WTS_SESSION_INFO)), typeof(WTS_SESSION_INFO));
if (WTS_CONNECTSTATE_CLASS.WTSActive == tSessionInfo.State)
{
IntPtr hToken = IntPtr.Zero;
if (WTSQueryUserToken(tSessionInfo.SessionID, out hToken))
{
PROCESS_INFORMATION tProcessInfo;
STARTUPINFO tStartUpInfo = new STARTUPINFO();
tStartUpInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
bool ChildProcStarted = CreateProcessAsUser(
hToken, // Token of the logged-on user.
ChildProcName, // Name of the process to be started.
null, // Any command line arguments to be passed.
IntPtr.Zero, // Default Process' attributes.
IntPtr.Zero, // Default Thread's attributes.
false, // Does NOT inherit parent's handles.
0, // No any specific creation flag.
null, // Default environment path.
null, // Default current directory.
ref tStartUpInfo, // Process Startup Info.
out tProcessInfo // Process information to be returned.
);
if (ChildProcStarted)
{
CloseHandle(tProcessInfo.hThread);
CloseHandle(tProcessInfo.hProcess);
}
else
{
ShowServiceMessage("CreateProcessAsUser失败", "CreateProcess");
}
CloseHandle(hToken);
break;
}
}
}
WTSFreeMemory(ppSessionInfo);
}
}
添加完后即可在service.cs的函数onStart中添加如下代码(随着电脑开启后启动服务调用这个程序):
win_Interop.CreateProcess(@"D:\新建文件夹\Video\bin\Release\Video.exe");
下面安装服务可以自己手动在cmd命令中输入(InstallUtil.exe后的是windows服务exe文件路径):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe C:\Users\Administrator\Desktop\WindowsService1\bin\Debug\WindowsService1.exe
安装完后即可在电脑----管理----服务里面找到自己设置的服务名看是否能找到,若能找到则可以测试电脑重启是否会开启程序。
卸载服务手动在cmd命令中输入:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u C:\Users\Administrator\Desktop\WindowsService1\bin\Debug\WindowsService1.exe
在程序里面设置安装服务和卸载服务把InstallUtil.exe 文件和WindowsService1.exe程序复制到主程序的目录下然后在主程序里添加代码:
public static void RunCmd(string cmd)
{
using (Process p = new Process())
{
p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true; //重定向标准错误输出
p.StartInfo.CreateNoWindow = true; //不显示程序窗口
p.Start();//启动程序
//向cmd窗口写入命令
p.StandardInput.WriteLine(cmd);
p.StandardInput.AutoFlush = true;
//获取cmd窗口的输出信息
//output = p.StandardOutput.ReadToEnd();
//p.WaitForExit();//等待程序执行完退出进程
p.Close();
}
}
//安装代码
// \"表示转译 路径有空格会导致cmd命令失败所以要注册cmd的形式:“c\is\installutil.exe”
dos = "\""+System.Windows.Forms.Application.StartupPath + "\\InstallUtil.exe\" " +"\""+ System.Windows.Forms.Application.StartupPath + "\\WindowsService1.exe \"";
ProcessStart.RunCmd(dos);
//卸载代码
dos = "\"" + System.Windows.Forms.Application.StartupPath + "\\InstallUtil.exe\" /u " + "\"" + System.Windows.Forms.Application.StartupPath + "\\WindowsService1.exe\"";
ProcessStart.RunCmd(dos);
附代码下载链接:https://download.csdn.net/download/qq_35319925/10895604