问题背景:
最近有大领导的硬盘坏了导致数据丢失,当然拿到外面去恢复,但没有全部恢复。所以这个incident就触发了一个问题, 如何避免发生类似的事情。所以我就想,能否尽可能早的检测出用户的硬盘的问题,在彻底坏之前就备份好数据并更换掉硬盘。
总体的思路:
我们知道如硬盘有问题了,比如坏道啊什么的,Windows系统会产生相应的一条日志。所以如果我们能够集中监测到用户的这类日志,就可以尽可能的避免数据丢失的事故发生。我们知道WINDOWS系统有一个event转发的功能,所以只要将所有用户的相应的日志转发到一台服务器上我们就可以实现集中监测了。同时我们知道:日志转发有两种方式:collector initiated和source initiated. Source initiated 我们可以用GPO,但我们的GPO都要鬼佬来approve,如这样天知道什么时候能approve,甚至都不会approve.所以我就选择collector initiated。但这样就产生一个问题,如何在每台机器上启用日志转发,另外这种方法的日志转发需要将服务器添加到在每台用户的本机管理员组内。
下面是源代码(需要NTSET Collection控件):
unit EventForwarding;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,ComObj,ComCtrls,
IdIcmpClient,StdCtrls, NTCommon, UserMan;
type
TForm1 = class(TForm)
Button1: TButton;
IdIcmpClient1: TIdIcmpClient;
Edit1: TEdit;
NTUserMan1: TNTUserMan;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Function PingResult(HostName:String):String;
Function RunDosCommand(Command: string): string;
Function GetTime(currenttime:TdateTime):String;
Function WaitExeFinish(const sExeName: string):boolean;
procedure Button1Click(Sender: TObject);
Procedure OpenExcel(Path:string;sheetnumber:Integer);
Function AddUserAccount(HostName,logonusername,logonpwd:string):string;
Function AddComputerAccount(HostName,logonusername,logonpwd:string):string;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1; ExcelApp:Variant;
implementation
{$R *.dfm}
Function Tform1.AddUserAccount(HostName,logonusername,logonpwd:string):String;
begin
NTUserman1.MachineName:=HostName;
NTUserman1.LogonAs.UserName:=logonusername;
NTUserman1.LogonAs.Password:=logonpwd;
Try
if (NTUserman1.ConnectIPC=0) then
begin
NTUserman1.UserName:='账号';
NTUserman1.MemberOfLocal.add('Administrators');
Result:='成功加入';
end else
begin
Result:='加入失败';
end
Except
Result:='异常';
end;
end;
Function Tform1.AddComputerAccount(HostName,logonusername,logonpwd:string):String;
begin
NTUserman1.MachineName:=HostName;
NTUserman1.LogonAs.UserName:=logonusername;
NTUserman1.LogonAs.Password:=logonpwd;
Try
if (NTUserman1.ConnectIPC=0) then
begin
NTUserman1.UserName:='服务器名';
NTUserman1.MemberOfLocal.add('Administrators');
Result:='成功加入';
end else
begin
Result:='加入失败';
end
Except
Result:='异常';
end;
end;
//执行DOS并返回结果
function Tform1.RunDosCommand(Command: string): string;
var
hReadPipe: THandle;
hWritePipe: THandle;
SI: TStartUpInfo;
PI: TProcessInformation;
SA: TSecurityAttributes;
// SD : TSecurityDescriptor;
BytesRead: DWORD;
Dest: array[0..1023] of char;
CmdLine: array[0..512] of char;
TmpList: TStringList;
Avail, ExitCode, wrResult: DWORD;
osVer: TOSVERSIONINFO;
tmpstr: AnsiString;
begin
osVer.dwOSVersionInfoSize := Sizeof(TOSVERSIONINFO);
GetVersionEX(osVer);
if osVer.dwPlatformId = VER_PLATFORM_WIN32_NT then
begin
// InitializeSecurityDescriptor(@SD, SECURITY_DESCRIPTOR_REVISION);
// SetSecurityDescriptorDacl(@SD, True, nil, False);
SA.nLength := SizeOf(SA);
SA.lpSecurityDescriptor := nil; //@SD;
SA.bInheritHandle := True;
CreatePipe(hReadPipe, hWritePipe, @SA, 0);
end
else
CreatePipe(hReadPipe, hWritePipe, nil, 1024);
try
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(TStartUpInfo);
SI.wShowWindow := SW_HIDE;
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.dwFlags := SI.dwFlags or STARTF_USESTDHANDLES;
SI.hStdOutput := hWritePipe;
SI.hStdError := hWritePipe;
StrPCopy(CmdLine, Command);
if CreateProcess(nil, CmdLine, nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, SI, PI) then
begin
ExitCode := 0;
while ExitCode = 0 do
begin
wrResult := WaitForSingleObject(PI.hProcess, 500);
// if PeekNamedPipe(hReadPipe, nil, 0, nil, @Avail, nil) then
if PeekNamedPipe(hReadPipe, @Dest[0], 1024, @Avail, nil, nil) then
begin
if Avail > 0 then
begin
TmpList := TStringList.Create;
try
FillChar(Dest, SizeOf(Dest), 0);
ReadFile(hReadPipe, Dest[0], Avail, BytesRead, nil);
TmpStr := Copy(Dest, 0, BytesRead - 1);
TmpList.Text := TmpStr;
Result := tmpstr;
finally
TmpList.Free;
end;
end;
end;
if wrResult <> WAIT_TIMEOUT then ExitCode := 1;
end;
GetExitCodeProcess(PI.hProcess, ExitCode);
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
end;
end;
Function Tform1.PingResult(HostName:String):String;
Begin
IdIcmpClient1.Host:=HostName;
Try
IdIcmpClient1.Ping;
if (IdIcmpClient1.replyStatus.BytesReceived=0) or (IdIcmpClient1.ReplyStatus.TimeToLive=0) then
begin
Result:='该机器不存在或不在线';
end else
begin
Result:='该机器存在';
end
Except
Result:='该机器不存在';
end;
end;
Function Tform1.GetTime(currenttime:TdateTime):String;
var Hour, Min,Sec, MSec:Word;
begin
DecodeTime(currenttime,Hour, Min,Sec, MSec);
if (Min>=55) then
begin
Result:=IntTostr(Hour+1)+':'+'05';
end else
if (Min<5) then
begin
Result:=IntTostr(Hour)+':'+'0'+IntTostr(Min+5);
end else
Result:=IntTostr(Hour)+':'+IntTostr(Min+5);
end;
Function Tform1.WaitExeFinish(const sExeName: string):boolean;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
b:boolean;
begin
//ShowMessage('Ready to launch NotePad...');
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
b:=CreateProcess( nil, PChar(sExeName), nil, nil, False, 0,
nil, nil, StartupInfo, ProcessInfo);
with ProcessInfo do
begin
CloseHandle(hThread);
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
end;
Result := b;
//ShowMessage('NotePad has terminated.');
end;
Procedure Tform1.OpenExcel(Path:String;sheetnumber:Integer);
Begin
ExcelApp:=CreateoleObject('Excel.Application');
ExcelApp.Visible:=True;
ExcelApp.Workbooks.Open(Path);
ExcelApp.Worksheets[sheetnumber].Activate;
End;
procedure TForm1.Button1Click(Sender: TObject);
var introw,sheet: integer;
pinable,targetTime,cmdstring,hostname,computername:string;
logonusername, logonpassword:string;
begin
sheet:=StrToInt(Trim(Edit2.Text));
OpenExcel(Edit1.Text,sheet);
introw:=2;
While not (ExcelApp.Cells[introw,7].value ='') do
begin
if (ExcelApp.Cells[introw,14].value ='') then
begin
hostname:=Trim(ExcelApp.cells[introw,7].value)+'.asia.jci.com';
computername:='\\'+hostname;
logonusername:=hostname+'\管理员账号';
logonpassword:=‘管理员账号密码;
ExcelApp.cells[introw,10].value:=form1.PingResult(hostname);
pinable:= ExcelApp.cells[introw,10].value;
if (pinable='该机器存在') then
begin
ExcelApp.cells[introw,12].value:=AddUserAccount(computername,logonusername,logonpassword);
ExcelApp.cells[introw,13].value:=AddComputerAccount(computername,logonusername,logonpassword);
targetTime:= GetTime(Now);
cmdstring:='schtasks /create /s '+hostname+' /sc once /TN EventForwarding /TR '+'"'+'C:\windows\system32\WinRm.cmd quickconfig -q'+'"'+' '+'/ST '+targetTime+' /ru '+'"'+'system'+'"';
ExcelApp.Cells[introw,11].value:=RunDosCommand(cmdstring);
end;
end;
introw:=introw+1;
end;
Showmessage('complete');
end;
end.