不打算把程序搞完了,代码记录一下来备忘
运行命令行程序获得返回码和反馈信息
//某些程序反馈信息是utf8的,需要转码 function AnsiToWide(const S: AnsiString): WideString; var len: integer; ws: WideString; begin Result:=''; if (Length(S) = 0) then exit; len:=MultiByteToWideChar(CP_ACP, 0, PChar(s), -1, nil, 0); SetLength(ws, len); MultiByteToWideChar(CP_ACP, 0, PChar(s), -1, PWideChar(ws), len); Result:=ws; end; function WideToUTF8(const WS: WideString): UTF8String; var len: integer; us: UTF8String; begin Result:=''; if (Length(WS) = 0) then exit; len:=WideCharToMultiByte(CP_UTF8, 0, PWideChar(WS), -1, nil, 0, nil, nil); SetLength(us, len); WideCharToMultiByte(CP_UTF8, 0, PWideChar(WS), -1, PChar(us), len, nil, nil); Result:=us; end; function AnsiToUTF8(const S: AnsiString): UTF8String; begin Result:=WideToUTF8(AnsiToWide(S)); end; function UTF8ToWide(const US: UTF8String): WideString; var len: integer; ws: WideString; begin Result:=''; if (Length(US) = 0) then exit; len:=MultiByteToWideChar(CP_UTF8, 0, PChar(US), -1, nil, 0); SetLength(ws, len); MultiByteToWideChar(CP_UTF8, 0, PChar(US), -1, PWideChar(ws), len); Result:=ws; end; function WideToAnsi(const WS: WideString): AnsiString; var len: integer; s: AnsiString; begin Result:=''; if (Length(WS) = 0) then exit; len:=WideCharToMultiByte(CP_ACP, 0, PWideChar(WS), -1, nil, 0, nil, nil); SetLength(s, len); WideCharToMultiByte(CP_ACP, 0, PWideChar(WS), -1, PChar(s), len, nil, nil); Result:=s; end; //运行命令行程序的 function GetRunConsoleResult(FileName:String;Visibility:Integer;var mOutputs:string):Integer; var sa:TSecurityAttributes; hReadPipe,hWritePipe:THandle; ret:BOOL; strBuff:array[0..255] of char; lngBytesread:DWORD; WorkDir:String; StartupInfo:TStartupInfo; ProcessInfo:TProcessInformation; begin FillChar(sa,Sizeof(sa),#0); sa.nLength := Sizeof(sa); sa.bInheritHandle := True; sa.lpSecurityDescriptor := nil; if not(CreatePipe(hReadPipe, hWritePipe, @sa, 0)) then begin Result:=-2; //通道创建失败 end; WorkDir:=ExtractFileDir(Application.ExeName); FillChar(StartupInfo,Sizeof(StartupInfo),#0); StartupInfo.cb:=Sizeof(StartupInfo); StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; StartupInfo.wShowWindow:=Visibility; StartupInfo.hStdOutput:=hWritePipe; StartupInfo.hStdError:=hWritePipe; if not CreateProcess(nil, PChar(FileName), { pointer to command line string } @sa, { pointer to process security attributes } @sa, { pointer to thread security attributes } True, { handle inheritance flag } NORMAL_PRIORITY_CLASS, nil, { pointer to new environment block } PChar(WorkDir), { pointer to current directory name, PChar} StartupInfo, { pointer to STARTUPINFO } ProcessInfo) { pointer to PROCESS_INF } then Result := INFINITE {-1 进程创建失败} else begin CloseHandle(hWritePipe); mOutputs:=''; while ret do begin FillChar(strBuff,Sizeof(strBuff),#0); ret := ReadFile(hReadPipe, strBuff, 256, lngBytesread, nil); mOutputs := mOutputs + strBuff; end; Application.ProcessMessages; //等待console结束 WaitforSingleObject(ProcessInfo.hProcess, INFINITE); GetExitCodeProcess(ProcessInfo.hProcess, Cardinal(Result)); CloseHandle(ProcessInfo.hProcess); { to prevent memory leaks } CloseHandle(ProcessInfo.hThread); CloseHandle(hReadPipe); end; end; //示例 var s,ftype:string; i:integer; t:tstringlist; begin i:=GetRunConsoleResult('rsync.exe',SW_HIDE,s); label1.Caption:=inttostr(i); s:=UTF8ToAnsi(s); //有些程序返回的换行符是#10,换成windows的#13#10 s:=stringreplace(s,#10,#13#10,[rfreplaceall]);
监控文件系统更改
//声明部分 const SHCNE_RENAMEITEM = $1; SHCNE_CREATE = $2; SHCNE_DELETE = $4; SHCNE_MKDIR = $8; SHCNE_RMDIR = $10; SHCNE_MEDIAINSERTED = $20; SHCNE_MEDIAREMOVED = $40; SHCNE_DRIVEREMOVED = $80; SHCNE_DRIVEADD = $100; SHCNE_NETSHARE = $200; SHCNE_NETUNSHARE = $400; SHCNE_ATTRIBUTES = $800; SHCNE_UPDATEDIR = $1000; SHCNE_UPDATEITEM = $2000; SHCNE_SERVERDISCONNECT = $4000; SHCNE_UPDATEIMAGE = $8000; SHCNE_DRIVEADDGUI = $10000; SHCNE_RENAMEFOLDER = $20000; SHCNE_FREESPACE = $40000; SHCNE_ASSOCCHANGED = $8000000; SHCNE_DISKEVENTS = $2381F; SHCNE_GLOBALEVENTS = $C0581E0; SHCNE_ALLEVENTS = $7FFFFFFF; SHCNE_INTERRUPT = $80000000; SHCNF_IDLIST = 0; // LPITEMIDLIST SHCNF_PATHA = $1; // path name SHCNF_PRINTERA = $2; // printer friendly name SHCNF_DWORD = $3; // DWORD SHCNF_PATHW = $5; // path name SHCNF_PRINTERW = $6; // printer friendly name SHCNF_TYPE = $FF; SHCNF_FLUSH = $1000; SHCNF_FLUSHNOWAIT = $2000; SHCNF_PATH = SHCNF_PATHW; SHCNF_PRINTER = SHCNF_PRINTERW; WM_SHNOTIFY = $401; NOERROR = 0; type PSHNOTIFYSTRUCT=^SHNOTIFYSTRUCT; SHNOTIFYSTRUCT = record dwItem1 : PItemIDList; dwItem2 : PItemIDList; end; Type PSHFileInfoByte=^SHFileInfoByte; _SHFileInfoByte = record hIcon :Integer; iIcon :Integer; dwAttributes : Integer; szDisplayName : array [0..259] of char; szTypeName : array [0..79] of char; end; SHFileInfoByte=_SHFileInfoByte; Type PIDLSTRUCT = ^IDLSTRUCT; _IDLSTRUCT = record pidl : PItemIDList; bWatchSubFolders : Integer; end; IDLSTRUCT =_IDLSTRUCT; function SHNotify_Register(hWnd : Integer) : Bool; function SHNotify_UnRegister:Bool; function SHEventName(strPath1,strPath2:string;lParam:Integer):string; Function SHChangeNotifyDeregister(hNotify:integer):integer;stdcall;external 'Shell32.dll' index 4; Function SHChangeNotifyRegister(hWnd,uFlags,dwEventID,uMSG,cItems:LongWord;lpps:PIDLSTRUCT):integer;stdcall;external 'Shell32.dll' index 2; Function SHGetFileInfoPidl(pidl : PItemIDList;dwFileAttributes : Integer;psfib : PSHFILEINFOBYTE;cbFileInfo : Integer;uFlags : Integer):Integer;stdcall;external 'Shell32.dll' name 'SHGetFileInfoA'; type UTF8String = AnsiString; function AnsiToWide(const S: AnsiString): WideString; function WideToUTF8(const WS: WideString): UTF8String; function AnsiToUTF8(const S: AnsiString): UTF8String; function UTF8ToWide(const US: UTF8String): WideString; function WideToAnsi(const WS: WideString): AnsiString; function UTF8ToAnsi(const S: UTF8String): AnsiString; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; Button2: TButton; RzPageControl1: TRzPageControl; TabSheet1: TRzTabSheet; TabSheet2: TRzTabSheet; TabSheet3: TRzTabSheet; RzMemo1: TRzMemo; RzCheckList1: TRzCheckList; RzSelectFolderDialog1: TRzSelectFolderDialog; Memo1: TMemo; RzGroupBox1: TRzGroupBox; RzCheckBox1: TRzCheckBox; RzCheckBox2: TRzCheckBox; RzSpinEdit1: TRzSpinEdit; RzCheckBox3: TRzCheckBox; RzLabel1: TRzLabel; procedure Button1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button2Click(Sender: TObject); private { Private declarations } public procedure WMShellReg(var Message:TMessage);message WM_SHNOTIFY; { Public declarations } { Public declarations } end; var Form1: TForm1; m_hSHNotify:Integer; m_pidlDesktop : PItemIDList; //函数部分 function SHEventName(strPath1,strPath2:string;lParam:Integer):string; var sEvent:String; begin case lParam of //根据参数设置提示消息 SHCNE_RENAMEITEM: sEvent := '重命名文件'+strPath1+'为'+strpath2; SHCNE_CREATE: sEvent := '建立文件 文件名:'+strPath1; SHCNE_DELETE: sEvent := '删除文件 文件名:'+strPath1; SHCNE_MKDIR: sEvent := '新建目录 目录名:'+strPath1; SHCNE_RMDIR: sEvent := '删除目录 目录名:'+strPath1; SHCNE_MEDIAINSERTED: sEvent := strPath1+'中插入可移动存储介质'; SHCNE_MEDIAREMOVED: sEvent := strPath1+'中移去可移动存储介质'+strPath1+' '+strpath2; SHCNE_DRIVEREMOVED: sEvent := '移去驱动器'+strPath1; SHCNE_DRIVEADD: sEvent := '添加驱动器'+strPath1; SHCNE_NETSHARE: sEvent := '改变目录'+strPath1+'的共享属性'; SHCNE_ATTRIBUTES: sEvent := '改变文件目录属性 文件名'+strPath1; SHCNE_UPDATEDIR: sEvent := '更新目录'+strPath1; SHCNE_UPDATEITEM: sEvent := '更新文件 文件名:'+strPath1; SHCNE_SERVERDISCONNECT: sEvent := '断开与服务器的连接'+strPath1+' '+strpath2; SHCNE_UPDATEIMAGE: sEvent := 'SHCNE_UPDATEIMAGE'; SHCNE_DRIVEADDGUI: sEvent := 'SHCNE_DRIVEADDGUI'; SHCNE_RENAMEFOLDER: sEvent := '重命名文件夹'+strPath1+'为'+strpath2; SHCNE_FREESPACE: sEvent := '磁盘空间大小改变'; SHCNE_ASSOCCHANGED: sEvent := '改变文件关联'; else sEvent:='未知操作'+IntToStr(lParam); end; Result:=sEvent; end; function SHNotify_Register(hWnd : Integer) : Bool; var ps: pidlstruct; begin {$R-} result := false; if m_hshnotify = 0 then begin //获取桌面文件夹的pidl if shgetspecialfolderlocation(0, CSIDL_DESKTOP, m_pidldesktop) <> noerror then form1.close; if boolean(m_pidldesktop) then begin new(ps); try ps.bwatchsubfolders := 1; ps.pidl := m_pidldesktop; // 利用shchangenotifyregister函数注册系统消息处理 m_hshnotify := shchangenotifyregister(hwnd, (shcnf_type or shcnf_idlist), (shcne_allevents or shcne_interrupt), wm_shnotify, 1, ps); result := boolean(m_hshnotify); finally FreeMem(ps); end; end else // 如果出现错误就使用 cotaskmemfree函数来释放句柄 cotaskmemfree(m_pidldesktop); end; {$R+} end; function SHNotify_UnRegister:Bool; begin Result:=False; If Boolean(m_hSHNotify) Then //取消系统消息监视,同时释放桌面的Pidl If Boolean(SHChangeNotifyDeregister(m_hSHNotify)) Then begin {$R-} m_hSHNotify := 0; CoTaskMemFree(m_pidlDesktop); Result := True; {$R-} End; end; procedure TForm1.WMShellReg(var Message: TMessage); //file://系统消息处理函数 var strPath1,strPath2:String; charPath:array[0..259]of char; pidlItem:PSHNOTIFYSTRUCT; begin pidlItem:=PSHNOTIFYSTRUCT(Message.wParam); //file://获得系统消息相关得路径 SHGetPathFromIDList(pidlItem.dwItem1,charPath); strPath1:=charPath; SHGetPathFromIDList(pidlItem.dwItem2,charPath); strPath2:=charPath; Memo1.Lines.Add(SHEvEntName(strPath1,strPath2,Message.lParam)+chr(13)+chr(10)); end; //注册监控 procedure TForm1.Button2Click(Sender: TObject); begin m_hSHNotify:=0; if SHNotify_Register(Form1.Handle) then begin //file://注册Shell监视 ShowMessage('Shell监视程序成功注册'); Button1.Enabled := False; end else ShowMessage('Shell监视程序注册失败'); end; //注销监控 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin //在程序退出的同时删除监视 if Boolean(m_pidlDesktop) then SHNotify_Unregister; end;