Windows开机自启动的API原理是向注册表
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
对应应用程序的运行路径,或者说启动命令,允许带参数。
HKEY_CURRENT_USER与HKEY_LOCAL_MACHINE
注册表HKEY_CURRENT_USER节点下的内容仅针对当前登录的用户生效,Windows是多账户系统(不是多用户系统,多用户允许同时多个用户登录使用当前计算机系统),不同账户下有不同的配置。
注册表HKEY_LOCAL_MACHINE节点下的内容都是针对系统所有用户生效的。
C#可以直接调用Windows API接口读写注册表
第一、实现写注册表的函数
private static bool WriteRegistryValue(RegistryKey regKey, String keyName, String value)
{
if (null == keyName || 0 == keyName.Trim().Length)
{
Console.WriteLine("WriteRegistryValue, invalid keyName: " + keyName);
return false;
}
if (null == value || 0 == value.Trim().Length)
{
Console.WriteLine("WriteRegistryValue, invalid value: " + value);
return false;
}
try
{
bool needChange = false;
String[] names = regKey.GetValueNames();
if (null != names)
{
for (int i = 0; i < names.Length; i++)
{
String oldValue = (String)regKey.GetValue(keyName, "");
if (null == oldValue || !oldValue.Equals(value))
{
needChange = true;
break;
}
}
}
if (needChange)
{
regKey.SetValue(keyName, value);
}
return true;
}
catch (SecurityException e)
{
Console.WriteLine("WriteRegistryValue, SecurityException ");
}
catch (ObjectDisposedException e)
{
Console.WriteLine("WriteRegistryValue, ObjectDisposedException");
}
catch (System.IO.IOException e)
{
Console.WriteLine("WriteRegistryValue, IOException");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("WriteRegistryValue, IOException");
}
return false;
}
第二、实现向注册表节点Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run写入数值的函数
public static String getAutoStartKeyName(String softwareName, String softwarePath)
{
if (null == softwareName || 0 == softwareName.Trim().Length)
{
return "";
}
if (null == softwarePath || 0 == softwarePath.Trim().Length)
{
return "";
}
String md5sum = Md5sum(softwarePath);
return softwareName + "_" + md5sum.Substring(0, 8);
}
public static bool setAutoStart(String softwareName, String softwarePath)
{
if (null == softwareName || 0 == softwareName.Trim().Length)
{
Console.WriteLine("invalid softwareName: " + softwareName);
return false;
}
if (null == softwarePath || 0 == softwarePath.Trim().Length)
{
Console.WriteLine("invalid softwarePath: " + softwarePath);
return false;
}
RegistryKey localMachineKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
RegistryKey regKeyRun = localMachineKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
RegistryKey regKeySoftware = null, regKeyMiscrosoft = null, regKeyWindows = null, regKeyCurrentVersion = null;
try
{
if (null == regKeyRun)
{
Console.WriteLine("openSubKey failed. try create it.");
regKeySoftware = localMachineKey.CreateSubKey("Software");
regKeyMiscrosoft = regKeySoftware.CreateSubKey("Microsoft");
regKeyWindows = regKeyMiscrosoft.CreateSubKey("Windows");
regKeyCurrentVersion = regKeyWindows.CreateSubKey("CurrentVersion");
regKeyRun = regKeyCurrentVersion.CreateSubKey("Run");
}
String keyName = getAutoStartKeyName(softwareName, softwarePath);
return WriteRegistryValue(regKeyRun, keyName, softwarePath);
}
finally
{
SafeCloseRegKey(regKeyRun); regKeyRun = null;
SafeCloseRegKey(regKeyCurrentVersion); regKeyCurrentVersion = null;
SafeCloseRegKey(regKeyWindows); regKeyWindows = null;
SafeCloseRegKey(regKeyMiscrosoft); regKeyMiscrosoft = null;
SafeCloseRegKey(regKeySoftware); regKeySoftware = null;
}
}
private static void SafeCloseRegKey(RegistryKey regKey)
{
if (null != regKey)
{
regKey.Close();
}
}
public static String Md5sum(String input)
{
// step 1, calculate MD5 hash from input
System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
大家注意到String getAutoStartKeyName(String softwareName, String softwarePath)函数,这里是为了防止注册表中的name存在相同的情况造成冲突,因此将程序路劲也放进去MD5计算生成唯一的name保证不会冲突。
第三、实现关闭自启动
其实就是将自启动信息从注册表中删除
public static bool RemoveAutoStart(String softwarePath)
{
if (null == softwarePath || 0 == softwarePath.Trim().Length)
{
return false;
}
RegistryKey localMachineKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
RegistryKey regKeyRun = localMachineKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (null == regKeyRun)
{
return false;
}
try
{
String[] names = regKeyRun.GetValueNames();
if (null == names || 0 == names.Length)
{
return false;
}
String value;
foreach (String name in names)
{
value = (String)regKeyRun.GetValue(name, "");
if (softwarePath.Equals(value))
{
regKeyRun.DeleteValue(name);
return true;
}
}
}
catch (SecurityException e)
{
Console.WriteLine("SecurityException");
}
catch (ObjectDisposedException e)
{
Console.WriteLine("ObjectDisposedException");
}
catch (System.IO.IOException e)
{
Console.WriteLine("IOException");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("IOException");
}
finally
{
SafeCloseRegKey(regKeyRun); regKeyRun = null;
}
return false; // TODO
}
第四、实现判断当前路径是否有自启动的方法
因为在本人工具中只设置当前用户的自启动,所以判断时只判断当前用户,如果需要所有用户请使用HKEY_LOCAL_MACHINE对应的参数
public static bool IsAutoStart(String softwarePath)
{
if (null == softwarePath || 0 == softwarePath.Trim().Length)
{
return false;
}
RegistryKey localMachineKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
RegistryKey regKeyRun = localMachineKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (null == regKeyRun)
{
return false;
}
try
{
String[] names = regKeyRun.GetValueNames();
if (null == names || 0 == names.Length)
{
return false;
}
String value;
foreach (String name in names)
{
value = (String)regKeyRun.GetValue(name, "");
if (softwarePath.Equals(value))
{
return true;
}
}
}
catch (SecurityException e)
{
Console.WriteLine("SecurityException");
}
catch (ObjectDisposedException e)
{
Console.WriteLine("ObjectDisposedException");
}
catch (System.IO.IOException e)
{
Console.WriteLine("IOException");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("IOException");
}
finally
{
SafeCloseRegKey(regKeyRun); regKeyRun = null;
}
return false;
}
因为小工具是自己使用的,所以没有考虑到全局用户,全局用户需要administrator权限,大家用VS编译时增加对应权限就可以了。