WMI介绍

1、WMI是什么?
WMI——Windows管理规范(Windows Management instrumentation)。
  • 是一项核心的Windows管理技术。
  • 采用统一的、基于开放标准的、可扩展的面向对象接口的系统管理基础结构。
  • 支持脚本编程,使管理员的日常管理自动化。
  • 提供了统一的机制让用户来管理本地和远程的计算机。
 
2、WMI和WBEM
WBEM——基于Web的企业管理规范(Web-Based Enterprise Management)。
  • 由微软在1996年首先提出,由DMTF(Distributed Management Task Force,分布式管理任务组)管理维护。
  • 其数据模型称为CIM(Common Information Model,公共信息模型),是一个面向对象的模型,统一定义了一组类和名称空间。
WMI是微软实现的WBEM版本
 
3、WMI能做什么?
WMI可以使用户通过编程、脚本或各类已有工具来访问其提供的功能和服务。
例如:
  • 在计算机上启动一个进程。
  • 设定在特定时间运行特定服务。
  • 远程关闭计算机。
  • 当磁盘余额小于预定值时记录到事件日志。
  • 管理、监测IIS/SQL/Exchange/SMS/MOM等微软系列产品。
  • 管理提供相应WMI Provider的第三方应用。
  • ……
 
4、WMI脚本
WMI和WMI脚本
使用VBScript等脚本语言和WSH,就可以写出通过WMI进行系统管理的脚本。
脚本是管理员利用WMI的最主要方式,所以很多时候提到WMI即指WMI脚本。
 
示例:查看C盘的可用容量,单位B
Set wmi = GetObject("winmgmts:\\")
Set objDisk = wmi.get("Win32_LogicalDisk.DeviceID='C:'")
Wscript.Echo objDisk.FreeSpace
 
5、WMI架构图
 
6、WMI脚本的基本结构
严格说来,WMI由四部分组成:
1. 公共信息模型对象管理器——CIMOM
2. 公共信息模型——CIM
3. WMI提供程序
4. WMI脚本对象库
 
其中其第1、2、3三个部分,在使用中很少加以区别,我们一般统称为CIM库。
 
所以我们可以认为WMI实际是由两部分组成:CIM库和WMI脚本对象库。在具体使用过程中,我们是通过WMI脚本对象库去访问CIM库,管理托管的资源。也就是说,在我们编写脚本的过程大致可以分为这么几步:
1. 创建WMI对象脚本库的指针实例;
2. 调用其实例的方法,连接到CIM库,并指明需要访问的资源的逻辑位置;
3. 获得托管资源也就是类的实例的集合;
4. 枚举实例,完成工作。
这几个步骤在我们将来编写的代码中可以明确的反映出来。
 

命名空间与路径

在WMI内部,使用了类似于驱动器中的文件夹与文件的管理方式。命名空间类似于文件夹,其中的CIM类则类似于文件夹。所有的CIM类都被分门别类地归入相应的命名空间,同一命名空间内不允许有重名的类存在,不同的两上命名空间下则允许重名的类出现。整个空间的根是名为root,其路径也采用了类似于驱动器路径的表达方式,比如\\MyWorkStation\root\cimv2:Win32_Processor就表示了MyWorkStation这台主机中root下cimv2空间中的Win32_Processor这个CIM类。这样的路径表示支持相对路径、绝对路径的表示方法,以当前连接的主机、当前打开的空间作为相对路径的原点,并忽略路径名称的大小写。
这个命名空间的结构可以通过一个类似于WMI CIM Studio这样的工具查看,还可以输入交互式的WQL语句进行联机查询。同一命名空间中的类保持了相应的继承关系,我们也可以添加自定义的命名空间和类。
 
据微软称,WMI的命名空间共有16个,不过不用担心,我们常用的只有两个:
1. root\cimv2 在这个命名空间里包括了绝大多数与计算机、操作系统相关联的类。
2. root\default 管理注册表的类
 

常用的脚本对象库

WMI脚本对象库由24个对象组成,在脚本中心有一副脚本库对象模型的图,作为入门,我们一般只用到其中的四个对象,其继承和层级关系如下:
SwbemLocator教本库对象→SwbemServicesWMI服务对象→SwbemObjectSet类实例集合对象→SwbemObject类的实例
现在让我们来举个例子,详细说明一下这四个对象在脚本中的应用方法:
例一:用来检索计算机上安装的光驱:
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer
Set colItems = objSWbemServices.ExecQuery("Select * from Win32_CDROMDrive")
For Each objItem in colItems
WScript.Echo "光盘驱动器的类型: " & objItem.Caption
WScript.Echo "盘符是: " & objItem.Id
Next
例二:用来检索CPU型号
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer
Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor")
For Each objSWbemObject In objSWbemObjectSet
Wscript.echo "CPU的型号为:" & objSWbemObject.name
Next
 
1、WMI服务的连接方法
方法一:
步骤一、建立SwbemLocator对象的实例。代码为:
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
然后用SwbemLocator对象的ConnectServer方法(SwbemLocator对象只有1个只读属性Security_和1个方法ConnectServer)建立WMI服务的连接,返回一个命名空间的连接(SwbemServices对象),代码为:
Set objSWbemServices = objSWbemLocator.ConnectServer()
ConnectServer方法共有8个参数,所有参数都是可选的,其参数格式如下:
ConnectServer([strComputName],[strNamespace],[strUser],[strPassword],[strLocale],[strAuthority],[iSecurityFlags],[objwbemNamedValueSet])
 
考虑到WMI的复杂性,在使用中我们如果只是在本地计算机上进行检索和查询,那么我们只需要设置第1、2个参数,其它参数都可以省略;如果想连接到远程计算机,一般需要对前4个参数进行设置,我们也只对此做个简单的介绍。
strServer——计算机名,缺省为本机,本机也可以用”.”
strNamespace——需要登录的CIM命名空间,例如:"root\CIMV2",缺省为"root\CIMV2"。
 
方法二:用moniker名字法建立WMI服务的连接,这也是微软推荐的连接方法
moniker名字法是利用GetObject函数直接建立WMI服务的连接,它的要点就是通过编写一个moniker字符串作为GetObject函数的参数,然后返回一个SwbemServices对象。
关于moniker字符串的完整格式如下:
"winmgmts:[{SecuritySettings}!][\\ComputerName][\Namespace][:ClassName][.KeyProperty='Value']"
"winmgmts:"是前缀,表示为WMI服务,必须使用;
第二部分用来验证权限和假冒级别的,省略。
第三部分为计算机名字:"\\.\"是计算机名字,默认可省略,其余同上;
第四部分CIM命名空间:缺省的命名空间为"root\CIMV2",默认可省略。
第五部分为类名。
第六部分为属性值。注意:当该moniker字符串不包括最后2项时(即为:"winmgmts:[\\ComputerName][\Namespace]"),则GetObject(moniker字符串)返回的是一个命名空间的已验证的连接(SwbemServices对象);当不包括最后1项时,返回的是一个CIM类(SWbemObject对象);当包括最后2项时,返回的是一个类的单独实例(SWbemObject对象)。
常见的moniker名字法建立WMI服务的连接:
1.连接到本机
Set objSWbemServices = GetObject("winmgmts:")
2.连接到远程计算机(默认名称空间)
Set objSWbemServices = GetObject("winmgmts:\\atl-dc-01\")
3.连接到远程计算机的特定名称空间
Set objSWbemServices = GetObject("winmgmts:\\atl-dc-01\root\default")
4.连接到远程计算机的特定类
Set objSWbemServices = GetObject("winmgmts:\\atl-dc-01\root\cimv2:Win32_OperatingSystem")
5.连接到远程计算机的特定实例
Set objSWbemServices = GetObject_
("winmgmts:\\atl-dc-01\root\cimv2:Win32_LogicalDisk.DeviceID='C:'")
 
2、获得类实例的方法
我们有4种方法获得类的实例,其中方法1和方法2是通过SwbemServices对象的InstancesOf方法和ExecQuery方法来获得某个类的多个实例组成的集合对象。方法3和方法4则是返回单独的类的实例,即返回的是一个SWbemObject对象。
1)InstancesOf方法获得类的实例集合
 
InstancesOf方法的语法参数格式如下:
SwbemServices.InstancesOf(strClass)
strClass为类名,例如"Win32_Service"
回顾例二,就是用语句:Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor") 来获得"Win32 Processor "类的所有实例集合,然后我们可以用
For Each objSWbemObject In objSWbemObjectSet
……
Next
语句获得每一个类的实例SWbemObject对象,然后就可以根据我们的需要,进行相应的操作。
 
2)ExecQuery方法获得类的实例集合
与InstancesOf方法不一样的是,ExecQuery方法可以通过查询语句,只返回匹配部分实例和属性。ExecQuery方法的语法参数格式如下:
SwbemServices.ExecQuery(strQuery)
strQuery为WMI查询语言(WQL)构造的一个查询语句字符串。
例如:
Set objSWbemObjectSet = objSWbemServices.ExecQuery("select ProcessorId from Win32_Processor where DeviceID='cpu0'")
 
3)Get方法获得一个类的实例(SWbemObject对象)
此方法也就不必再用 For Each objSWbemObject In objSWbemObjectSet :……:Next
语句从SWbemObjectSet对象中获得每一个类的实例SWbemObject对象,Get方法的语法参数格式如下:
SwbemServices.Get([strObjectPath][.KeyProperty='Value'])
strObjectPath是类的名字
KeyProperty是主键属性名
Value是指定的主键属性值
这里要注意的是如果要获得一个类的实例,则strObjectPath.KeyProperty='Value'中的任何一项都不能省略,例如:
Set objSWbemServices = GetObject("winmgmts:")
Set objSWbemObject = objSWbemServices.Get("Win32_Processor.DeviceID='cpu0'")
Wscript.echo “CPU的型号为”:" & objSWbemObject.ProcessorId
结果一样,脚本却简化了不少。
 
4)直接用moniker名字法获得一个类的实例
在说明Moniker名字法的时候我们说过,当包括最后2项时,返回的是一个类的单独实例,如:Set objSWbemObject = GetObject("winmgmts:Win32_Processor.DeviceID='cpu0'")
Wscript.echo "首枚CPU序列号:" & objSWbemObject.ProcessorId
是不是更加简单?仅仅2条语句就获得了CPU的序列号。
 

WQL查询语言

1、WQL简介
WQL就是WMI中的查询语言,WQL全称是WMI Query Language,简称为WQL,翻译成中文好像可以成为Windows管理规范查询语言。熟悉SQL语言会感觉它和SQL非常相似。
WQL其实非常简单,它有如下特点:
  • 每个WQL语句必须以SELECT开始
  • SELECT后跟你要查询的属性名(对应SQL的字段名),也可以像SQL一样,以*表示所有属性值
  • FROM后跟关键字
  • 查询的类名字
  • 另外,如果你想精确查询结果还可以加上WHERE条件从句。比如某个类有Enable属性,你可以在查询的时候加上WHERE ENABLE=true。
  • WQL是SQL的一个子集,但不支持更新、删除和排序等操作,可用于返回选定实例的选定属性
 
2、WQL详述
1.语法
SELECT properties[,properties] FROM class [where clause]
 
2.参数
  • SELECT 必选项。代表WQL语句的开始,
  • properties 必选项。代表想查询的属性名字。可以是多个属性名,也可查询所有属性值,用*代替。
  • FROM 必选项。跟在properties的后面。
  • Class 必选项。代表想要查询的类的名称。
  • where clause 可选项。where 从句和相关条件语句,用来缩小查询范围。
 
2.逻辑运算
  • AND运算符,连接两个逻辑运算,当同时满足条件时通过。
  • OR运算符,连接两个逻辑运算,当至少一个满足条件时通过。
例子:
SELECT * FROM Win32_LogicalDisk WHERE (DriveType = 2) OR (DriveType = 3 AND FreeSpace < 1000000)
 
4.比较运算
  • =                等于
  • >               大于
  • <             小于
  • <=      小于等于
  • >=      大于等于
  • <> 或 != 不等于
  • Is [not]      [不]是,仅仅用于比较NULL的时候
例子:
SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NULL
SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NOT NULL
SELECT * FROM Win32_LogicalDisk WHERE DriveType IS 5
SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NOT "NTFS"
 
5.Like运算
描述:模糊匹配查询的条件
通配符
  • "%"代表一个或者多个字符。 例如,%Office%可代表"My Offices," "Office VPN,"或"Office." Office%可代表"Offices"或"Office VPN,"但是不能代表"My Offices,"
  • "[ ]”返回参数范围。 例如"[A-Z]ars"可代替"Mars," "Wars," and "Tars,"但是不能代替"Stars."
  • "^"取范围的反面。 例如"[^A-M]ars"可代替"Wars"和"Tars,"但是不能代替"Mars"因为"M"不再指定范围内。
  • "_"代替单个字符。 "M_rs"可代替"Mars," "M3rs,"
 
6.判断运算
描述:有的类的属性只有TRUE和FALSE两种状态,这个时候可以使用TRUE和FALSE来判断,记住这个时候不能使用is TRUE来判断,因为他只适用于判断NULL。
例子:
SELECT * FROM Win32_NetworkAdapterConfiguration WHERE DHCPEnabled = TRUE
 
7.相关查询
描述:检索与指定内容相关的所有实例并且返回查询结果。
语法:ASSOCIATORS OF
参数:
ASSOCIATORS OF {描述}
ASSOCIATORS OF {ObjectPath}
说明:
假设有四个实例,A,B,X和Y,其中A与X相关,B与Y相关
执行ASSOCIATORS OF {A}仅仅会返回一个X,如果还有其他的关系,也许会返回两个或者以上的实例。
例子:
Query:
ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="C:"}
Results:
Win32_Directory.Name="C:\\"
Win32_ComputerSystem.Name="mycomputer"
Win32_DiskPartition.DeviceID="Disk #0, Partition #0"
 
其他WQL关键字
  • __CLASS 在查询结果集中对象继承的类对象引用。
  • GROUP Clause GROUP子句使WMI生成一个表示一组事件的通知。
  • ISA ISA运算符是WQL特定的运算符,可以在事件查询中使用。当ISA包含在事件查询的WHERE子句中时,它将请求类层次结构中而不是特定事件类中所有类的事件通知。
  • WITHIN 指定轮询的间隔或者分组区间,一般在event查询中使用此子句。
  • REFERENCES OF 获取所有引用特定源实例的关联实例集,一般在schema和data查询中使用,REFERENCES OF语句与ASSOCIATORS OF 语句类似,。
  • KEYSONLY 在REFERENCES OF和ASSOCIATORS OF 查询中用来确认返回的结果实例集中只有关键的实例/属性被填充。以此来降低查询的调用成本。
 
示例1:查询服务(Win32_Service)中所有正在运行的实例的服务名称、服务描述
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\"&strComputer&"\root\cimv2")
Set colServices = objSWbemServices.ExecQuery("SELECT * FROM Win32_Service Where state = 'Running'")
WScript.Echo "服务名称---服务描述"
For Each objService In colServices
WScript.Echo objService.name&"---"&objService.Description
Next
 
示例2:查询账户(Win32_Account)中所有实例的账户名称、账户描述、账户SID
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\"&strComputer&"\root\cimv2")
Set colAccounts = objSWbemServices.ExecQuery("SELECT * FROM Win32_Account")
WScript.Echo "账户名称---账户描述---账户SID"
For Each objAccount In colAccounts
WScript.Echo objAccount.name&"---"&objAccount.Description&"---"&objAccount.SID
Next
 
示例3:查询当前进程的名称、PID、占用内存空间(单位MB)
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\"&strComputer&"\root\cimv2")
Set colProcess = objSWbemServices.ExecQuery("SELECT * FROM Win32_Process")
WScript.Echo "进程名称---PID---所占内存"
For Each objProcess In colProcess
m = Int(CSng(objProcess.WorkingSetSize)/1024/1024*100)/100
WScript.Echo objProcess.name&"---"&objProcess.ProcessId&"---"& CStr(m)&"MB"
Next
 

WMI事件监控与处理

很多人在平常会有事件监控的需要,如监控进程的运行监视移动磁盘的插入、监视文件系统的操作等等。WMI可以很容易地实现上述功能。
那么WMI是如何实现事件监控功能的呢?原来,WMI能访问Windows下的API组件并能接收其运行时的InstanceCreationEvent(创建或启动事件)、InstanceDeletionEvent(删除或关闭事件)、InstanceNotificationEvent(修改或变更事件)、InstanceOperationEvent(所有事件)的返回状态,从而判断事件的性质而实现对事件的监控。
 
示例1:监测是否新建了一个记事本
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\"&strComputer&"\root\cimv2")
Set objEventSource = objSWbemServices.ExecNotificationQuery( _
"SELECT * FROM __InstanceCreationEvent " _
& "WITHIN 5" _
& "WHERE TargetInstance ISA 'Win32_Process'" _
& "AND TargetInstance.Name = 'NotePad.exe'")
Set objEventObject = objEventSource.NextEvent()
WScript.Echo "记事本已打开"
 
事件处理的函数与方法:
ExecNotificationQuery 函数
执行查询以接收事件。 调用会立即返回,并且调用方可以在返回的事件发生时轮询返回的枚举器。 释放返回的枚举器将取消查询。
SWbemEventSource.NextEvent方法
如果事件是可用的,NextEvent所述的方法SWbemEventSource对象检索从事件查询该事件。
 
分析:
第1、2行,定义空间名称并连接WMI服务
第3行,使用ExecNotificationQuery函数执行查询接收事件
第4行,查询创建或启动事件类对象,注意__InstanceCreationEvent前面是两条下划线
第5行,WITHIN指监测的一个周期,WITH 5表示每隔5秒进行一次监测
第6、7行,将查询范围定在Notepad.exe进程
第8、9行,如果事件可用,即打开了Notepad.exe,输出消息"记事本已打开"
 
示例2:监控U盘的状态
On Error Resume Next
Dim objWMI, objSHELL, objEvents, objEvent
Set objWMI = GetObject("Winmgmts:\\.\Root\Cimv2")
Set objSHELL = CreateObject("Wscript.Shell")
Set objEvents = objWMI.ExecNotificationQuery _
("Select * From __InstanceOperationEvent Within 5 " _
& "Where TargetInstance Isa 'Win32_LogicalDisk' " _
& "And TargetInstance.DriveType = 2")
Do While True
Set objEvent = objEvents.NextEvent()
Select Case objEvent.Path_.Class
Case "__InstanceCreationEvent"
objSHELL.Popup "检测到盘符号为" & objEvent.TargetInstance.Name & "的U盘插入",3,"系统提示"
Case "__InstanceDeletionEvent"
objSHELL.Popup "盘符号为" & objEvent.TargetInstance.Name & "的U盘被移除",3,"系统提示"
End Select
Loop
 
分析:
第1行,该语句的作用是,如果后面的程序出现"运行时错误"时,会继续运行,不中断的
第2行,声明变量
第3行,定义空间名称并连接WMI服务
第4行,声明WshShell对象,用于后面的弹窗显示
第5行,使用ExecNotificationQuery函数执行查询接收事件
第6行,查询所有事件类对象
第7、8行,从中筛选出属于Win32_LogicalDisk组件中移动磁盘(TargetInstance.DriveType = 2)发生的属性实例(TargetInstance)
第9、17行,设置了一个Do While…Loop循环实现对事件的无限监控
第10行,如果事件可用,执行后面语句
第11-16行,使用Switch选择语句,若插入U盘,则触发InstanceCreationEvent事件,执行第13行代码,弹出显示框;若拔出U盘,则触发InstanceDeletionEvent事件,执行第15行代码,弹出显示框
 
示例3:实时监控新增进程
On Error Resume Next
Dim objWMI, objSHELL, objEvents, objEvent, Message, Return
Set objWMI = GetObject("Winmgmts:\\.\Root\Cimv2")
Set objSHELL = CreateObject("Wscript.Shell")
Set objEvents = objWMI.ExecNotificationQuery _
("Select * From __InstanceCreationEvent Within 3 " _
& "Where TargetInstance Isa 'Win32_Process'")
Do While True
Set objEvent = objEvents.NextEvent()
Message = "新进程" & objEvent.TargetInstance.Name _
& "被启动,请在10秒内点击确认允许,否则系统将强行关闭!"
Return = objSHELL.Popup(Message,10,"系统警告",0+48)
If Return = -1 Then
Return = objEvent.TargetInstance.Terminate
If return <> 0 Then
Message = "进程" & objEvent.TargetInstance.Name _
& "关闭失败,请尝试手动关闭!"
objSHELL.Popup Message,3,"系统警告",0+48
End If
End If
Loop

VBS脚本编程(10)——编写WMI脚本的更多相关文章

  1. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

  2. 【在 Nervos CKB 上做开发】Nervos CKB脚本编程简介[2]:脚本基础

    CKB脚本编程简介[2]:脚本基础 原文作者:Xuejie 原文链接:Introduction to CKB Script Programming 2: Script 本文译者:Shooter,Jas ...

  3. 【Shell脚本编程系列】Shell脚本开发的习惯和规范

    1.开头指定脚本解释器 #!/bin/sh或#!/bin/bash 2.开头加版本版权信息 #Date #Author #Mail #Function #Version 提示:可配置vim编辑文件时自 ...

  4. 从此编写 Bash 脚本不再难【转】

    从此编写 Bash 脚本不再难 原创 Linux技术 2017-05-02 14:30 在这篇文章中,我们会介绍如何通过使用 bash-support vim 插件将 Vim 编辑器安装和配置 为一个 ...

  5. shell脚本编程(一) 变量、条件判断、循环

    目录   1. shell脚本编程   2. 运行 Shell 脚本有两种方法   3. 变量   4. 本地变量   5. 环境变量   6. 参数变量   7. 多行注释   8. if条件判断 ...

  6. 【VI Script】你不知道的脚本编程

    前言 近期,小黑在写程序的时候,经常会遇到一些重复性的工作.尤其是在写到QMH(Queued Message Handler)程序时,经常需要创建UI界面上的一些控件引用,并且在程序中捆绑成簇使用. ...

  7. Vbs 脚本编程简明教程之一

    —为什么要使用 Vbs ? 在 Windows 中,学习计算机操作也许很简单,但是很多计算机工作是重复性劳动,例如你每周也许需要对一些计算机文件进行复制.粘贴.改名.删除,也许你每天启动 计算机第一件 ...

  8. 关于shell脚本编程的10个最佳实践

    每一个在UNIX/Linux上工作的程序员可能都擅长shell脚本编程.但大家解决问题的方式却不尽相同,这要取决于对专业知识的掌握程度.使 用命令的种类.看待问题的方式等等.对于那些处在shell脚本 ...

  9. shell脚本编程的10个最佳实践

    摘要:每一个在UNIX/Linux上工作的程序员可能都擅长shell脚本编程.对于那些处在shell脚本编程初级阶段的程序员来说,遵循一些恰当的做法可以帮助你更快.更好的学习这些编程技巧. 每一个在U ...

随机推荐

  1. Mybatis学习之自定义持久层框架(六) 自定义持久层框架:完善CRUD方法并进行测试

    前言 没想到会等到半年以后才来写这篇文章,我已经不记得当初自己想要在这篇文章中写什么了,还好有一些零散的笔记留着,就对照着上一篇文章及零散的笔记,把内容给补充完吧. 完善CRUD方法 完善Defaul ...

  2. FreeSWITCH的安装与使用

    FreeSWITCH

  3. NABCD-name not found

    项目 内容 课程 2020春季计算机学院软件工程(罗杰 任健) 作业要求 团队项目选择 项目名称 FOTT 项目内容 在OCR-Form-Tools开源项目的基础上,扩展功能,支持演示更多的API,例 ...

  4. 通过CRM系统改变传统工作模式

    在现在这个互联网时代,同行业的竞争越发激烈,因此许多企业都选择使用CRM来提高企业的销售业绩.CRM客户关系管理系统是能够优化企业的销售流程.维护良好的客户关系.对销售流程进行管理的强大工具.但是很多 ...

  5. CRM系统实施中如何避免“踩雷”

    CRM系统实施后,效果没有达到预期是很多企业出现的情况.而最主要的原因就是在实施之前没有足够的思考和相应的计划.那么,企业应如何避免CRM系统实施时"踩雷"?这里有几条建议希望可以 ...

  6. 解决SSH自动断线,无响应的问题。

    解决SSH自动断线,无响应的问题. 3 Replies 在连接远程SSH服务的时候,经常会发生长时间后的断线,或者无响应(无法再键盘输入). 总体来说有两个方法: 1.依赖ssh客户端定时发送心跳. ...

  7. Mysql不知道默认密码情况下登录/重置/忘记密码

    场景一: 基础系统:linux 镜像:LAMP环境(Ubuntu 18.04 Apache PHP7.0) 问题:ERROR 1405 (28000): Access denied for user ...

  8. git OpenSSL SSL_connect问题

    遇到这个问题,查找别人也遇到,省时间不写了直接复制 在使用Git来克隆仓库报了错误,如下: fatal: unable to access 'https://github.com/xingbuxing ...

  9. 【Java】Jackson解析xml的坑

    为了获取xml数据,在spring mvc中针对 @ResponseBody配置了jackson. 刚用的时候内心是狂喜的,终于不用自己解析了----  but----------还是有坑的-- 坑一 ...

  10. 优秀电路资料--- IOT方案

    完整的IOT方案 http://www.cirmall.com/circuit/4117/%E3%80%90%E5%BC%80%E6%BA%90%E3%80%91%E5%AE%8C%E6%95%B4% ...