Leona+
Dream for future
Dream for future
Apr 6th
Apr 1st
连接到服务器上之后,第一步要做的当然是拿到虚拟机的列表了:
private ManagementObjectCollection RefreshVirtualMachines()
{
ManagementScope scope = new ManagementScope(@"\\" + ServerName + @"\root\virtualization");
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM MsVM_ComputerSystem WHERE Caption LIKE 'Virtual%' ");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
return searcher.Get();
}
很简单吧,一个查询就搞定了。得到的ManagementObjectCollection中的每个ManagementObject,对应一个虚拟机的数据。接下来就是生成虚拟机的对象:
public class VirtualMachine
{
internal VirtualMachine(ManagementObject obj)
{
BaseObject = obj;
}
private ManagementObject BaseObject { get; set; }
public string Name
{
get
{
return BaseObject.GetPropertyValue("ElementName").ToString();
}
}
public VirtualMachineState State
{
get
{
return VirtualMachineState.GetState(BaseObject.GetPropertyValue("EnabledState").ToString());
}
}
public Guid Id
{
get
{
return new Guid(BaseObject.GetPropertyValue("Name").ToString());
}
}
public TimeSpan UpTime
{
get
{
return TimeSpan.FromMilliseconds((double)(ulong)BaseObject.GetPropertyValue("OnTimeInMilliseconds"));
}
}
}
每个ManagementObject中包含一个虚拟机的数据,详细的列表在这里。不过我只找到4个有用的:Name, ElementName, EnabledState和OnTimeInMilliseconds:
EnabledState是一个字符串形式的数字,要把它转换成用户看得懂的数据,还需要一个类:
public class VirtualMachineState
{
private VirtualMachineState(ushort id, string name, string displayName)
{
Id = id;
Name = name;
DisplayName = displayName;
}
public string Name { get; private set; }
public ushort Id { get; private set; }
public string DisplayName { get; private set; }
public override string ToString()
{
return DisplayName + " (" + Id + ")";
}
public static VirtualMachineState GetState(string name)
{
ushort id = 0;
bool useId = UInt16.TryParse(name, out id);
foreach (VirtualMachineState state in states)
{
if ((useId && state.Id == id) || (state.Name == name))
{
return state;
}
}
return Unknown;
}
private static List states = new List();
static VirtualMachineState()
{
states.Add(Unknown);
states.Add(Enabled);
states.Add(Disabled);
states.Add(Paused);
states.Add(Suspended);
states.Add(Starting);
states.Add(Sanpshotting);
states.Add(Saving);
states.Add(Stopping);
states.Add(Pausing);
states.Add(Resuming);
}
public static VirtualMachineState Unknown = new VirtualMachineState(0, "Unknown", "Unknown");
public static VirtualMachineState Enabled = new VirtualMachineState(2, "Enabled", "Running");
public static VirtualMachineState Disabled = new VirtualMachineState(3, "Diabled", "Off");
public static VirtualMachineState Paused = new VirtualMachineState(32768, "Paused", "Paused");
public static VirtualMachineState Suspended = new VirtualMachineState(32769, "Suspended", "Saved");
public static VirtualMachineState Starting = new VirtualMachineState(32770, "Starting", "Starting");
public static VirtualMachineState Sanpshotting = new VirtualMachineState(32771, "Snapshotting", "Snapshooting");
public static VirtualMachineState Saving = new VirtualMachineState(32773, "Saving", "Saving");
public static VirtualMachineState Stopping = new VirtualMachineState(32774, "Stopping", "Shuting down");
public static VirtualMachineState Pausing = new VirtualMachineState(32776, "Pausing", "Pausing");
public static VirtualMachineState Resuming = new VirtualMachineState(32777, "Resuming", "Resuming");
}
用VirtualMachineState.GetState把ManagementObject里的EnableState转化成VirtualMachineState。一共有11种可能的状态,最常见的Enabled和Disabled,即开着和关着。
这样就可以获取服务器上的所有虚拟机的信息,然后显示给用户了。
Mar 26th
Hyper-V是Virtual Server的升级版,主要用于运行和管理虚拟机。它的优点是可以同时管理和维护多台虚拟机,在不需要某台虚拟机的时候,可以把它关掉,用到再开开来,相比于使用物理机器,Hyper-V可以更好的优化资源的利用。利用强大的快照(Snapshot)功能,可以省去重装机器的烦恼。比如在机器刚装好的时候,做一个快照,用了一会觉得系统有问题了,再恢复到之前的状态,就相当于重装了一遍机器了。
Windows Server 2008 (及R2)中提供了一个直观的Hyper-V的管理界面,不仅可以管理本机的虚拟机,也可以连到别的服务器上去。但这毕竟是用户界面,需要手工操作的。在人们越来越懒的时代,我们更希望有自动化的管理,比如每隔一小时刷新一下虚拟机的状态,看看哪台机器不正常,然后发一封邮件出来……生活是多么惬意呀……
接下来开始第一步,连接到远程的Hyper-V服务器。Hyper-V的API是基于WMI的。至于WMI是什么,就不多说了,直接上代码:
public static VirtualSystemService Connect(string serverName)
{
ManagementObject service = null;
try
{
ManagementScope scope = new ManagementScope(@"\\" + serverName + @"\root\virtualization");
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM MsVM_VirtualSystemManagementService");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject obj in coll)
{
service = obj;
}
}
catch (ManagementException)
{
return null;
}
if (service == null)
{
return null;
}
return new VirtualSystemService(service, serverName);
}
第一行中的VirtualSystemService是一个自定义类型,用于对Hyper-V的控制。关键代码是第7行,当目标机器上没有Hyper-V服务的时候,scope.Connect();会抛出一个异常……不多说了,这段代码还是很简单易懂的。
Mar 25th
貌似没有很优美的做法,只能把%Path%按分号分割,然后一段一段地比较。
:InPath [In]Path [Out]0/1
SETLOCAL
SET LocalPathCopy=%PATH%
SET Result=0
:WHILE
IF "%LocalPathCopy%" == "" GOTO WEND
FOR /F "delims=;" %%I IN ("%LocalPathCopy%") DO (
IF /I "%%~I" == "%~1" (
SET Result=1
GOTO WEND
)
)
FOR /F "delims=; tokens=1,*" %%I IN ("%LocalPathCopy%") DO (
SET LocalPathCopy=%%~J
)
GOTO WHILE
:WEND
:InPathRet
ENDLOCAL & SET %2=%Result% & GOTO :EOF
使用方法:
SET x=C:\Windows Call :InPath %x% Result IF %Result% == 0 SET Path=%Path%;%x%
Mar 21st
自从Vista带来了UAC之后,应用程序就变成了两种,有管理员权限的,和没有管理员权限的。一些老的应用程序会莫名其妙地出错,这时候就要考虑右击应用程序,然后“以管理员身份运行”。这还不是什么大问题,exe文件的右键菜单里都会有这个,但是对于一些脚本文件(cmd, js一类)来说,就没那么方便了。通常需要重新开一个带管理员权限的命令行窗口,然后打很多cd回到刚的文件夹,然后再运行脚本,相当麻烦。
搜了一下,找到一个解决办法。把下面的代码保存为Elevate.js:
var command = WScript.Arguments.Item(0);
var argument = "";
for (var i = 0; i < WScript.Arguments.Count(); ++i){
argument += WScript.Arguments.Item(i) + " ";
}
try{
var shellapp = new ActiveXObject("Shell.Application");
shellapp.ShellExecute(command, argument, null, "runas", 1);
}
catch(e){
WScript.Echo("Something wrong: " + e.description);
}
以后要以管理员身份运行程序的时候,只要输入“Elevate <exefile> <arguments>”就可以了,比如“Elevate cmd /k”。
当然,这个逃不过UAC的检查,还是会有一个对话框弹出来要点“确定”的。
Mar 15th
Mar 4th
小无聊一下,不过真的很强大……
@ECHO OFF
SETLOCAL
SET X=10
CALL :Fib %X% Y
ECHO Fib^(%X%^)=%Y%
GOTO :EOF
:Fib [In]X [Out]Result
SETLOCAL
SET A=%1
SET D=1
SET E=0
IF %A% LEQ 1 (
GOTO FibRet
)
SET /A B=%A%-1
SET /A C=%A%-2
CALL :Fib %B% D
CALL :Fib %C% E
:FibRet
ENDLOCAL & SET /A %2=%D%+%E% & GOTO :EOF
输出是“Fib(10)=89”
Mar 4th
获取当前的小时数:
@ECHO OFF
SET Hour=%TIME:~0,2%
IF %Hour% GTR 12 (
ECHO Afternoon
) ELSE (
ECHO Morning
)
打印Windows的版本:
@ECHO OFF
FOR /F "tokens=1,2,3,4" %%I IN ('VER') DO (
SET Ver_Temp=%%L
)
SET Ver_Major=%Ver_Temp:~0,1%
SET Ver_Minor=%Ver_Temp:~2,1%
SET Ver_Build=%Ver_Temp:~-5,4%
ECHO Windows Version:
ECHO Major %Ver_Major%
ECHO Major %Ver_Minor%
ECHO Build %Ver_Build%