编辑本段SC命令功能
  SC命令是XP系统中功能强大的DOS命令,SC命令能与“服务控制器”和已安装设备进行通讯。SC命令的功能有
  1、SC可以 检索和设置有关服务的控制信息。可以使用 SC.exe 来测试和调试服务程序。
  2、可以设置存储在注册表中的服务属性,以控制如何在启动时启动服务应用程序,以及如何将其作为后台程序运行。即更改服务的启动状态。
  3、SC 命令还可以用来删除系统中的无用的服务。(除非对自己电脑中的软硬件所需的服务比较清楚,否则不建议删除任何系统服务,尤其是基础服务)
  4、SC命令 的参数可以配置指定的服务,检索当前服务的状态,也可以停止和启动服务(功能上类似NET STOP/START命令,但SC速度更快且能停止更多的服务)。
  5、可以创建批处理文件来调用不同的 SC 命令,以自动启动或关闭服务序列。
  SC.exe 提供的功能类似于“控制面板”中“管理工具”项中的“服务”。
编辑本段SC命令列表及格式
  SC命令不能单独使用,必须和其它的命令结合起来一起使用。一共有24个,如下所示
  sc boot sc config sc continue sc control sc create sc delete sc descrīption sc enumdepend
  sc failure sc getdisplayname sc getkeyname sc interrogate sc lock sc pause sc qc
  sc qdescrīption sc qfailure sc query sc queryex sc querylock sc sdset sc sdshow
  sc start sc stop
  在命令行中直接输入SC会显示SC命令的帮助信息,直接输入以上24个命令除sc query 和 sc queryex之外都将显示该SC命令的帮助信息。(输入sc query和sc queryex会显示当前系统中正在运行的所有服务的详细信息,但sc queryex比sc query显示的信息多出来两项:PID和FLAGS)
  SC命令的格式:SC [Servername] command Servicename [Optionname= Optionvalues]
  Servername:指定服务所在的远程服务器的名称。名称必须采用通用命名约定 (UNC) 格式(“\\myserver”)。要在本地运行SC.exe,请忽略此参数。
  command :即以上提到的那24个命令(SC后面的那个,如query,start,stop,create,config等)
  Servicename:服务名,也就是要配置的那个服务的名字,例如你要启动一个服务你就输入sc start +你要启动的服务名。(注意这里的服务名不是服务的显示名称,而是服务名称,这个服务名称可以在系统管理工具下的服务中可以看到,例如在服务中双击DHCP Client可以看到其服务名称是Dhcp,而那个DHCP Client是显示名称,可以用sc命令来更改一个服务的显示名称)
  Optionname= Optionvalues:是选项名和选项的值。
  例如你要在开机是系统自动加载themes服务,你可以使用sc config themes start= auto,后面的start就是选项,auto是选项的值。(注意=号后面有个空格,所有的使用选项的在=号后面都要加个空格再加上选项值)
编辑本段SC命令的用法
  下面给出每个命令详细的用法
  1、sc boot
  表明最近的启动是否应该保存为上次已知的正确配置。
  语法
  Sc [ServerName] boot [{bad | OK}]
  参数
  ServerName:上面已经介绍,在此不在累述(下同)
  [{bad | OK}]
  指定最近的启动是否错误或它是否应该保存为上次已知的正确启动配置。
  下面的示例显示了如何使用 sc boot 命令:
  sc boot ok
  sc boot bad
  2、sc config
  修改注册表和“服务控制管理器”数据库中服务项目的值。
  语法
  Sc [ServerName] config [ServiceName] [type= {own | share | kernel | filesys | rec | adapt | interacttype= {own | share}}] [start= {boot | system | auto | demand | disabled}] [error= {normal | severe | critical | ignore}] [binpath= BinaryPathName] [group= LoadOrderGroup] [tag= {yes | no}] [depend= dependencies] [obj= {AccountName | ObjectName}] [displayname= DisplayName] [password= Password]
  ServiceName
  指定要操作的服务名。(上面也已经介绍,下文不在累述)
  type= {own | share | kernel | filesys | rec | adapt | interacttype= {own | share}}
  指定服务类型。
  own
  服务以其自身的进程运行。不与其他服务共享可执行文件。这是默认值。
  share
  服务作为共享进程运行。与其他服务共享可执行文件。
  kernel
  驱动程序。
  filesys
  文件系统驱动程序。
  rec
  文件系统识别驱动程序(标识计算机上使用的文件系统)。
  adapt
  适配器驱动程序(标识键盘、鼠标、磁盘驱动器这样的硬件项)。
  interact
  服务可以与桌面交互,接收用户的输入。交互服务必须在 LocalSystem 帐户下运行。该类型必须与 type= own 或 type= shared(例如,type= interact type= own)结合使用。自身使用 type= interact 将会产生参数无效的错误。
  start= {boot | system | auto | demand | disabled}
  指定服务的启动类型。
  boot
  由启动加载程序加载的设备驱动程序。
  system
  在核心初始化过程中启动的设备驱动程序。
  auto
  每次计算机重新启动时都会自动启动、并且即使无人登录到计算机也能正常运行的服务。
  demand
  必须手动启动的服务。如果没有指定 start=,则此项即为默认值。
  disabled
  不能启动的服务。要启动禁用的服务,应将启动类型更改为其他值。
  error= {normal | severe | critical | ignore}
  如果在启动过程中,服务启动失败,则指定错误的严重性。
  normal
  将记录错误,并且显示消息对话框,通知用户服务启动失败。启动将继续。这是默认设置。
  severe
  记录错误(如果存在)。计算机尝试以最新的有效配置重新启动。这可能导致计算机能够重新启动,但服务却仍然无法运行。
  critical
  记录错误(如果存在)。计算机尝试以最新的有效配置重新启动。如果上次已知正确的配置失败,启动也将失败,启动进程将以停止错误而中止。
  ignore
  错误已记录,启动继续。记录错误超出在事件ri志的范围,不再给用户作出提示。
  binpath= BinaryPathName
  指定指向服务二进制文件的路径。
  group= LoadOrderGroup
  指定该服务所属组的名称。组列表存储在注册表的 HKLM\System\CurrentControlSet\Control\ServiceGroupOrder 子项中。默认设置为空值。
  tag= {yes | no}
  指定是否在 CreateService 调用中获得 TagID。标记仅用于引导启动或系统启动驱动程序。
  depend= dependencies
  指定必须在此项服务之前启动的服务或组的名称。名称以正斜杠 (/) 分隔。
  obj= {AccountName | ObjectName}
  指定运行服务将使用的帐户名,或指定运行驱动程序将使用的 Windows 驱动程序对象名。默认设置为 LocalSystem。
  displayname= DisplayName
  指定一个可以在用户界面程序中用于为用户标识服务的友好的、有意义的名称。例如,一项服务的子项名是对用户毫无意义的 wuauserv,而显示的名称是“自动更新”。
  password= Password
  指定一个密码。如果使用了非 LocalSystem 的帐户,则此项是必需的。
  备注
  如果参数及其值之间没有空格,(例如,是 type= own,而不是 type=own),则操作会失败。
  示例
  下面的示例显示了如何使用 sc config 命令:
  sc config NewService binpath= "ntsd -d c:\windows\system32\NewServ.exe"
  3、sc continue
  为了恢复暂停的服务,要给服务发送一个 CONTINUE 控制请求。
  语法
  Sc [ServerName] continue [ServiceName]
  参数
  ServerName:略
  ServiceName:略
  备注
  使用 continue 操作来恢复暂停的服务。
  下面的示例显示了如何使用 sc continue 命令:
  sc continue tapisrv
  4、sc control
  向服务发送 CONTROL 。
  语法
  sc [ServerName] control [ServiceName] [{paramchange | netbindadd | netbindremove | netbindenable | netbinddisable | UserDefinedControlB}]
  参数
  {paramchange | netbindadd | netbindremove | netbindenable | netbinddisable | UserDefinedControlB}
  指定要发送到服务的控制。
  5、sc create
  在注册表和“服务控制管理器”中为服务创建子项和项目。
  语法
  Sc [ServerName] create [ServiceName] [type= {own | share | kernel | filesys | rec | adapt | interacttype= {own | share}}] [start= {boot | system | auto | demand | disabled}] [error= {normal | severe | critical | ignore}] [binpath= BinaryPathName] [group= LoadOrderGroup] [tag= {yes | no}] [depend= dependencies] [obj= {AccountName | ObjectName}] [displayname= DisplayName] [password= Password]
  参数:各个参数的作用参见sc config 命令
  下面的示例显示了如何使用 sc create 命令:
  sc \\myserver create NewService binpath= c:\windows\system32\NewServ.exe
  sc create NewService binpath= c:\windows\system32\NewServ.exe type= share start= auto depend= "+TDI Netbios"
  6、sc delete
  从注册表中删除服务子项。如果服务正在运行或者另一个进程有一个该服务的打开句柄,那么此服务将标记为删除。
  语法
  Sc [ServerName] delete [ServiceName]
  参数:略
  备注
  使用“添加或删除程序”删除 DHCP、DNS 或任何其他内置的操作系统服务。“添加或删除程序”不仅会删除该服务的注册表子项,而且还会卸载该服务并删除其所有的快捷方式。
  下面的示例显示了如何使用 sc delete 命令:
  sc delete newserv
  7、sc descrīption
  设置服务的描述字符串。
  语法
  Sc [ServerName] descrīption [ServiceName] [Descrīption]
  参数:略
  描述
  为指定服务指定描述。这个描述的内容可以在控制面板-管理工具-服务里通过查看该服务的属性看到。如果没有指定字符串,则不会修改该服务的描述。不限制服务描述中可包含的字符数。
  示例
  下面的示例显示了如何使用 sc descrīption 命令:
  sc descrīption newserv "Runs quality of service control."
  8、sc enumdepend
  枚举依赖此服务的系统组件,这也可以从控制面板-管理工具-服务里通过查看该服务的属性中的依存关系选项卡看到(“下面的系统组件依赖此服务”下面的部分)
  语法
  Sc [ServerName] enumdepend [ServiceName] [BufferSize]
  参数
  BufferSize
  以字节为单位指定枚举缓冲区的大小。默认值为 1024 字节。
  备注
  如果缓冲区不够大,enumdepend 操作只会部分输出依存关系,并指定输出所有依存关系所需的额外缓冲区大小。如果输出被截断,请重新运行该操作并指定更大的缓冲区大小。
  下面的示例显示了如何使用 sc enumdepend 命令:
  sc enumdepend rpcss 5690
  sc enumdepend tapisrv
  9、sc failure
  指定服务失败时要采取的措施。
  语法
  Sc [ServerName] failure [ServiceName] [reset= ErrorFreePeriod] [reboot= BroadcastMessage] [command= CommandLine] [actions= FailureActionsAndDelayTime]
  参数
  reset= ErrorFreePeriod
  指定没有失败的周期长度(单位为秒),此后失败计数应该重置为 0。这个参数必须与 actions= 参数结合使用。
  reboot= BroadcastMessage
  指定服务失败时要广播的消息。
  command= CommandLine
  指定服务失败时要运行的命令行。有关在失败时如何运行批处理或 VBS 文件的详细信息,请参阅“注释”。
  actions= FailureActionsAndDelayTime
  指定失败操作及其延迟时间(单位为毫秒),以正斜杠 (/) 隔开。以下操作均有效:run、restart 和 reboot。此参数必须与 reset= 参数结合使用。失败后不采取任何操作时,请使用 actions= ""。
  备注
  并非所有服务都允许更改其失败选项。其中一些作为服务集的一部分运行。
  要在失败时运行批处理文件,请指定 cmd.exeDrive:\FileName.bat 为 command= 参数,其中 Drive:\FileName.bat 是批处理文件的完全合格的名称。
  要在失败时运行 VBS 文件,请指定 cscrīpt drive:\myscrīpt.vbs 为 command= 参数,其中 Drive:\myscrīpt.vbs 是脚本文件完全合格的名称。
  可以将三种不同的操作指定为 actions= 参数,它们将会在服务的第一次、第二次、第三次失败时使用。
  如果参数及其值之间没有空格,(例如,是 type= own,而不是 type=own),则操作会失败。
  下面的示例显示了如何使用 sc failure 命令:
  sc failure msftpsvc reset= 30 actions= restart/5000
  sc failure dfs reset= 60 command= c:\windows\services\restart_dfs.exe actions= run/5000
  sc failure dfs reset= 60 actions= reboot/30000
  sc failure dfs reset= 60 reboot= "The Distributed File System service has failed.Because of this, the computer will reboot in 30 seconds." actions= reboot/30000
  sc failure myservice reset= 3600 reboot= "MyService crashed -- rebooting machine" command= "%windir%\MyServiceRecovery.exe" actions= restart/5000/run/10000/reboot/60000
  10、sc getdisplayname
  获得与特定服务关联的显示名称。
  语法
  Sc [ServerName] getdisplayname [ServiceName] [BufferSize]
  参数
  BufferSize
  指定缓冲区大小(以字节为单位)。默认值为 1024 字节。
  下面的示例显示了如何使用 sc getdisplayname 命令:
  sc getdisplayname clipsrv
  sc getdisplayname tapisrv
  sc getdisplayname sharedaccess
  11、sc getkeyname
  使用特定服务的显示名称作为输入的内容会获得与其相关联的项名。
  语法
  sc [ServerName] getkeyname [ServiceDisplayName] [BufferSize]
  参数
  ServiceDisplayName
  指定服务的显示名称。
  BufferSize
  指定缓冲区大小(以字节为单位)。默认值为 1024 字节。
  备注
  如果 ServiceDisplayName 包含空格,请使用引号将文本引起来(例如,"Service Display Name")。
  下面的示例显示了如何使用 sc getkeyname 命令:
  sc getkeyname "remote procedure call (rpc)"
  sc getkeyname "internet connection sharing"
  sc getkeyname clipbook
  12、sc interrogate
  向服务发送一个 INTERROGATE 控制请求。
  语法
  Sc [ServerName] interrogate [ServiceName]
  参数:略
  备注
  向服务发送 INTERROGATE 会导致该服务使用“服务控制管理器”更新其状态。
  下面的示例显示了如何使用 sc interrogate 命令:
  sc interrogate sharedaccess
  sc interrogate rpcss
  13、sc lock
  锁定“服务控制管理器”的数据库。
  语法
  sc [ServerName] lock
  参数:略
  备注
  锁定“服务控制管理器”的数据库会阻止启动任何服务。如果要确保服务在停止之后不会启动,请使用这个命令。这可以使您不受干扰地进行一些操作(例如,删除服务)。
  使用 lock 操作锁定“服务控制管理器”的数据库,然后通过键入 u 来使数据库解锁。也可停止锁定数据库的进程。
  下面的示例显示了如何使用 sc lock 命令:
  sc lock
  14、sc pause
  向服务发送 PAUSE 控制请求。
  语法
  Sc [ServerName] pause [ServiceName]
  参数:略
  备注
  在终止服务之前使用 pause 操作来暂停它。
  并非所有服务都能够被暂停。
  在暂停时并非所有服务都执行同样的操作。一些服务继续为现有客户端服务,但拒绝接受新的客户端。其他的会终止对现有客户端的服务,同时也会拒绝接受新的客户端。
  下面的示例显示了如何使用 sc pause 命令:
  sc pause tapisrv
  15、sc qc
  查询服务的配置信息。
  语法
  Sc [ServerName] qc [ServiceName] [BufferSize]
  参数
  BufferSize
  指定缓冲区大小(以字节为单位)。默认值为 1024 字节。
  备注
  qc 操作可以显示有关服务的下列信息:
  SERVICE_NAME(服务的注册表子项名称)、TYPE、ERROR_CONTROL、BINARY_PATH_NAME、LOAD_ORDER_GROUP、TAG、DISPLAY_NAME、DEPENDENCIES 和 SERVICE_START_NAME。
  管理员可以使用 SC 来确定任一服务的二进制名称,并查明它是否与其他服务共享一个进程,在命令行下键入下列命令:
  sc qc ServiceName
  SC 有助于将 Microsoft 管理控制台 (MMC) 的服务节点中的服务与“系统监视器”中的进程进行匹配。如果二进制名称是 Services.exe,那么服务共享“服务控制器”进程。
  Services.exe 启动所有的服务。为节约系统资源,几个为 Windows 开发的 Win32 服务被编写为共享 Services.exe 进程。这些服务不作为独立的进程列在“系统监视器”或“任务管理器”之中。Svchost.exe 也是如此,它是许多操作服务共享的服务主机进程。
  因为第三方 Win32 服务也可以配置为共享进程,所以不可能为每一个 Win32 服务创建一个进程。SC 可以用来获得这些服务的配置信息。但是,如果一项服务不与其他服务共享其进程,那么在服务运行时,“系统监视器”中会出现其进程。
  因为 SC 与包含在 Windows 中的 Services.exe 相比,提供了有关服务的更为详细和准确的信息,所以对于服务开发人员来说,SC 更有用处。Services.exe 可以确定服务是正在运行、已停止还是已暂停。尽管这些工具对于正在平稳运行的已调试应用程序已经足够,但它们提供的有关正开发的服务的信息却会使人误解。例如,正在启动的服务不管其实际运行与否都显示为已启动。
  SC 可执行对所有 Windows 服务控制应用编程接口 (API) 函数的调用。通过在命令行下指定这些函数来设置其参数。
  使用 SC,可以查询服务状态,检索存储在状态结构字段中的值。Services.exe 不能提供服务的完整状态,但 SC 可以显示精确的服务状态,以及最新的检查点号码和等待提示。可以将检查点用作调试工具,原因在于它表明了在程序停止响应之前初始化进行的程度。SC 也可以用来指定远程计算机名,以便于在远程计算机上调用服务 API 函数或查看服务状态结构。
  下面的示例显示了如何使用 sc qc 命令:
  sc qc \\myserver newsrvice
  sc qc rpcss 248
  16、sc qdescrīption
  显示服务的描述字符串。
  语法
  Sc [ServerName] qdescrīption [ServiceName] [BufferSize]
  参数
  BufferSize
  指定缓冲区大小(以字节为单位)。默认值为 1024 字节。
  下面的示例显示了如何使用 sc qdescrīption 命令:
  sc qdescrīption rpcss
  sc qdescrīption rpcss 138
  17、sc qfailure
  显示指定服务失败时要执行的操作。
  语法
  Sc [ServerName] qfailure [ServiceName] [BufferSize]
  参数
  BufferSize
  指定缓冲区大小(以字节为单位)。默认值为 1024 字节。
  备注
  qfailure 操作可以显示有关服务的下列信息:SERVICE_NAME(服务的注册表子项名)、RESET_PERIOD、REBOOT_MESSAGE、COMMAND_LINE 和 FAILURE_ACTIONS。
  下面的示例显示了如何使用 sc qfailure 命令:
  sc qfailure rpcss
  sc qfailure rpcss 20
  18、sc query
  获得和显示关于指定的服务、驱动程序、服务类型或驱动程序类型的信息。
  语法
  Sc [ServerName] query [ServiceName] [type= {driver | service | all}] [type= {own | share | interact | kernel | filesys | rec | adapt}] [state= {active | inactive | all}] [bufsize= BufferSize] [ri= ResumeIndex] [group= GroupName]
  参数
  ServiceName
  指定由 getkeyname 操作返回的服务名。此 query 参数不与其他的 query 参数结合使用(除了 ServerName)。
  type= {driver | service | all}
  指定需要枚举的内容。默认类型为 service。
  driver
  指定仅枚举驱动程序。
  service
  指定仅枚举服务。
  all
  指定同时枚举驱动程序和服务。
  type= {own | share | interact | kernel | filesys | rec | adapt}
  指定要枚举的服务类型或驱动程序类型。
  own
  服务以其自身的进程运行。不与其他服务共享可执行文件。这是默认值。
  share
  服务作为共享进程运行。与其他服务共享可执行文件。
  interact
  服务可以与桌面交互,接收用户的输入。交互服务必须在 LocalSystem 帐户下运行。
  kernel
  驱动程序。
  filesys
  文件系统驱动程序。
  state= {active | inactive | all}
  指定要枚举的服务的已开始状态。默认状态是 active。
  active
  指定所有的活动服务。
  inactive
  指定所有暂停或停止的服务。
  all
  指定所有服务。
  bufsize= BufferSize
  以字节为单位指定枚举缓冲区的大小。默认大小为 1024 字节。当从查询返回的显示结果超过 1024 个字节时,增加枚举缓冲区的大小。
  ri= ResumeIndex
  指定开始或继续枚举的索引号。默认值为 0。 在查询返回的信息超过默认缓冲区能够显示的大小时,请与 bufsize= 参数结合使用这个参数。
  group= GroupName
  指定要枚举的服务组。默认设置为所有组。
  备注
  如果参数及其值之间没有空格,(例如,是 type= own,而不是 type=own),则操作会失败。
  query 操作可以显示有关服务的下列信息:SERVICE_NAME(服务的注册表子项名)、TYPE、STATE(以及不可用的状态)、WIN32_EXIT_B、SERVICE_EXIT_B、CHECKPOINT 和 WAIT_HINT。
  在某些情况下,type= 参数可以使用两次。type= 参数的第一次出现指定是否查询服务、驱动器或所有这些项。type= 参数的第二次出现指定一个由 create 操作进一步缩小查询范围的类型。
  当 query 命令的显示结果超过了枚举缓冲区的大小时,显示类似于以下内容的消息:
  Enum: more data, need 1822 bytes start resume at index 79
  要显示剩余的 query 信息,请重新运行 query,将 bufsize= 设置为所需的字节数,并将 ri= 设置为指定的索引。例如,在命令行键入下面的指令会显示剩余的输出:
  sc query bufsize= 1822 ri= 79
  下面的示例显示了如何使用 sc query 命令:
  sc query
  sc query messenger
  sc query type= driver
  sc query type= service
  sc query state= all
  sc query bufsize= 50
  sc query ri= 14
  sc query type= service type= interact
  sc query type= driver group= ndis
  19、sc queryex
  获得和显示关于指定的服务、驱动程序、服务类型或驱动程序类型的扩展信息。
  语法
  Sc [ServerName] queryex [type= {driver | service | all}] [type= {own | share | interact | kernel | filesys | rec | adapt}] [state= {active | inactive | all}] [bufsize= BufferSize] [ri= ResumeIndex][group= GroupName]
  参数
  ServiceName
  指定由 getkeyname 操作返回的服务名。此 queryex 参数不与 ServerName 之外的任何其他 queryex 参数结合使用。
  type= {driver | service | all}
  指定需要枚举的内容。默认类型为 service。
  driver
  指定仅枚举驱动程序。
  service
  指定仅枚举服务。
  all
  指定同时枚举驱动程序和服务。
  type= {own | share | interact | kernel | filesys | rec | adapt}
  指定要枚举的服务类型或驱动程序类型。
  own
  服务以其自身的进程运行。不与其他服务共享可执行文件。这是默认值。
  share
  服务作为共享进程运行。与其他服务共享可执行文件。
  interact
  服务可以与桌面交互,接收用户的输入。交互服务必须在 LocalSystem 帐户下运行。
  kernel
  驱动程序。
  filesys
  文件系统驱动程序。
  state= {active | inactive | all}
  指定要枚举的服务的已开始状态。默认状态是 active。
  active
  指定所有的活动服务。
  inactive
  指定所有暂停或停止的服务。
  all
  指定所有服务。
  bufsize= BufferSize
  以字节为单位指定枚举缓冲区的大小。默认大小为 1024 字节。
  ri= ResumeIndex
  指定开始或继续枚举的索引号。默认值为 0。
  group= GroupName
  指定要枚举的服务组。默认设置为所有组。
  备注
  如果参数及其值之间没有空格,(例如,是 type= own,而不是 type=own),则操作会失败。
  queryex 操作可以显示有关服务的下列信息:SERVICE_NAME(服务的注册表子项名)、TYPE、STATE(以及不可用的状态)、WIN32_EXIT_B、SERVICE_EXIT_B、CHECKPOINT、WAIT_HINT、PID 和 FLAGS。
  在某些情况下,type= 参数可以使用两次。type= 参数的第一次出现指定是否查询服务、驱动器或所有这些项。type= 参数的第二次出现指定一个由 create 操作进一步缩小查询范围的类型。
  当 queryex 命令的显示结果超过了枚举缓冲区的大小时,显示类似于以下内容的消息:
  Enum: more data, need 2130 bytes start resume at index 75
  要显示剩余的 queryex 信息,请重新运行 queryex,将 bufsize= 设置为所需的字节数,并将 ri= 设置为指定的索引。例如,在命令行键入下面的指令会显示剩余的输出:
  sc queryex bufsize= 2130 ri= 75
  下面的示例显示了如何使用 sc queryex 命令:
  sc queryex messenger
  sc queryex group= ""
  20、sc querylock
  查询和显示“服务控制管理器”数据库的锁定信息。
  语法
  Sc [ServerName] querylock
  参数:略
  21、sc sdset
  使用“服务描述符定义语言 (SDDL)”来设置服务的安全描述符。
  语法
  Sc [ServerName] sdset ServiceName ServiceSecurityDescrīptor
  参数
  ServiceSecurityDescrīptor
  在 SDDL 中指定服务描述符。
  备注
  有关 SDDL 的详细信息,请参阅 Microsoft 网站上的 Security Descrīptor Definition Language(安全描述符定义语言)。
  22、sc sdshow
  使用 SDDL 显示服务的安全描述符。
  语法
  Sc [ServerName] sdshow ServiceName
  参数:略
  备注
  有关 SDDL 的详细信息,请参阅 Microsoft 网站上的 Security Descrīptor Definition Language(安全描述符定义语言)。
  示例
  sc sdshow rpcss
  23、sc start
  启动正在运行的服务。
  语法
  Sc [ServerName] start ServiceName [ServiceArguments]
  参数
  ServiceArguments
  指定传递给要启动的服务的服务参数。
  下面的示例显示了如何使用 sc start 命令:
  sc start tapisrv
  24、sc stop
  向服务发送 STOP 控制请求。
  语法
  Sc [ServerName] stop ServiceName
  参数:略
  备注
  并非所有服务都能够被停止。
  下面的示例显示了如何使用 sc stop 命令:
  sc stop tapisrv
posted @ 2008-10-15 09:46 小马歌 阅读(286) | 评论 (0)编辑 收藏
 

SC命令是XP系统中功能强大的DOS命令,SC命令能与“服务控制器”和已安装设备进行通讯。
安装服务:sc create serviceName binPath= "D:\server.exe"        [注意binPath= 之后有一个空格,必须有]

卸载服务:sc delete serviceName

or check HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices

以上修改要重起机器才能生效

另:
启动服务:net start serviceName 或sc start serviceName
停止服务:net stop serviceName 或sc stop serviceName

[SC命令 的参数可以配置指定的服务,检索当前服务的状态,也可以停止和启动服务(功能上类似NET STOP/START命令,但SC速度更快且能停止更多的服务)。]

posted @ 2008-10-15 09:39 小马歌 阅读(642) | 评论 (0)编辑 收藏
 
   到 深圳周边城市 坐汽车比较方便,提供个查询地址:
http://jt.sz.bendibao.com/keche/search.asp 
posted @ 2008-10-13 12:14 小马歌 阅读(242) | 评论 (0)编辑 收藏
 
估计是查看了qq的相关信息,自动创建的,地址:http://xiaomage234.woku.com

这种方式蛮新奇的
posted @ 2008-10-07 14:28 小马歌 阅读(100) | 评论 (0)编辑 收藏
 
说是,小三必修课
    
    其实,是所有情场中人的扒皮戏。
    
    《画皮》是一个惊喜,有些是无心,有些是故意。
    
    因为戏路太善良,我们总是忍不住笑场。
    
    然而,面对,那些太刻意的真情告白……我们如果不笑,难道要跟着哭吗?
    
    这场戏,需要些时间沉淀,然后,就有人像我们回忆八十年代的港片一样来回忆这张《画皮》。
    
    不如把笑点抖一抖,顺便帮着大家扭曲一下逻辑。
    
    这个故事告诉我们生活中的许多大道理。
    
    故事的基本结构是这样的。
    
    
    
    陈坤和甄子丹本来是战友,两个人都喜欢赵薇。赵薇选择了嫁给陈坤,甄子丹愤而远走。
    画皮定律一:再好的朋友,抢一个心上人,也会翻脸。无论男女。
    
    陈坤救了一个女人周迅回家。周迅其实是妖怪。
    画皮定律二:如果一个有家的男人把一个单身女子带回家,这绝对是场冒险,不管这个姑娘会不会画皮。
    
    赵薇怀疑陈坤喜欢周迅,进而发觉周迅来了之后,城里开始死人。认准周迅就是妖怪,
    画皮定律三:如果一个女人发现自己的男人外面有了女人,那么到处跟人说那个女人是狐狸精,只能显得自己像个疯子,太小气。
    
    
    但是没有人相信她。她写信喊来了甄子丹。
    画皮定律四:还是去找自己的旧情人,是正路!(找旧情人来干什么,看你的兴趣)
    
    
    周迅想嫁给陈坤,不是做妾,而是做夫人。
    画皮定律五:如果一个小三,喜欢上了一个有妇之夫,又不像只是玩一玩就吃掉他,而是想要个名分,会搞得三个人都很凄惨。
    
    甄子丹来了,降魔者孙丽也来了,孙丽看着甄子丹很有感觉,甄子丹对孙丽也有点感觉。
    画皮定律六:男人终究是要变心的,不管他当初多么爱你,只不过是动手没动手的差别,而且,总是有更年轻的姑娘出现的!!
    
    还有个蜥蜴精追随周迅而来,蜥蜴精爱着狐狸精周迅,周迅不喜欢他。
    画皮定律七:讨厌长得不帅的男人,女人讨厌“长舌头”的男人,讨厌知道自己当年底细的男人,讨厌,吃的东西,跟自己口味不同的男人……之后数条,都是第一条的借口。
    
    
    甄子丹表示自己相信赵薇,赵薇说甄子丹是个好人。
    画皮定律八:如果一个人给你发了“好人卡”,基本来说,这个人打算送死你去,吃定你一辈子了。不知道逃的,是傻瓜。
    
    
    周迅想色诱陈坤,蜥蜴精吃醋,进攻陈坤,大闹府里。
    画皮定律九:在两个女人之间摇摆的男人,比较吃香。在两个男人之间摇摆的女人,其实比较危险。女人斗心计,男人斗体力。
    
    
    蜥蜴精又进攻赵薇,关键时刻,陈坤选择去保护赵薇。
    画皮定律十:所有的男人,都会先考虑自己的老婆的,小三们的悲哀…… 其实,不是因为他更看重老婆,而是他的身份促使他必须先救自己的老婆,否则,会被人说,没有人味。
    
    周迅终于明白,陈坤更在乎身为老婆的赵薇。
    画皮定律十一:情人早晚会发现真相的,这个时候,怎么选择,能比较出一个人的智商。
    
    于是周迅直接胁迫赵薇离开,逼赵薇服毒。
    画皮定律十二:偷情的乐趣,就在于偷偷摸摸,有人争抢的感觉比较刺激,直接逼宫……注定是悲剧
    
    …………正邪开始大决战!!
    
    
    
    所谓,凡事,不能十三点。那就到此为止吧。
    
    爱情这种事情,都不能仔细推敲,一推敲,就千疮百孔。
  
  
   爱情经不起推敲,幸福的是,你总是在某个时刻,还相信你会爱上,死心塌地
posted @ 2008-10-06 14:38 小马歌 阅读(189) | 评论 (0)编辑 收藏
 
鉴于rsa加密的重要性和相关源代码的匮乏,经过整理特此贴出。需要下载bcprov-jdk14-123.jar。
  
  import javax.crypto.Cipher;
  import java.security.*;
  import java.security.spec.RSAPublicKeySpec;
  import java.security.spec.RSAPrivateKeySpec;
  import java.security.spec.InvalidKeySpecException;
  import java.security.interfaces.RSAPrivateKey;
  import java.security.interfaces.RSAPublicKey;
  import java.io.*;
  import java.math.BigInteger;
  
  /**
  * RSA 工具类。提供加密,解密,生成密钥对等方法。
  * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
  *
  */
  public class RSAUtil {
  
  /**
  * 生成密钥对
  * @return KeyPair
  * @throws EncryptException
  */
  public static KeyPair generateKeyPair() throws EncryptException {
  try {
  KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
  new org.bouncycastle.jce.provider.BouncyCastleProvider());
  final int KEY_SIZE = 1024;//没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
  keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  KeyPair keyPair = keyPairGen.genKeyPair();
  return keyPair;
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  * 生成公钥
  * @param modulus
  * @param publicExponent
  * @return RSAPublicKey
  * @throws EncryptException
  */
  public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws EncryptException {
  KeyFactory keyFac = null;
  try {
  keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  } catch (NoSuchAlgorithmException ex) {
  throw new EncryptException(ex.getMessage());
  }
  
  RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
  try {
  return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
  } catch (InvalidKeySpecException ex) {
  throw new EncryptException(ex.getMessage());
  }
  }
  /**
  * 生成私钥
  * @param modulus
  * @param privateExponent
  * @return RSAPrivateKey
  * @throws EncryptException
  */
  public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws EncryptException {
  KeyFactory keyFac = null;
  try {
  keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  } catch (NoSuchAlgorithmException ex) {
  throw new EncryptException(ex.getMessage());
  }
  
  RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
  try {
  return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
  } catch (InvalidKeySpecException ex) {
  throw new EncryptException(ex.getMessage());
  }
  }
  /**
  * 加密
  * @param key 加密的密钥
  * @param data 待加密的明文数据
  * @return 加密后的数据
  * @throws EncryptException
  */
  public static byte[] encrypt(Key key, byte[] data) throws EncryptException {
  try {
  Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  cipher.init(Cipher.ENCRYPT_MODE, key);
  int blockSize = cipher.getBlockSize();//获得加密块大小,如:加密前数据为128个byte,而key_size=1024 加密块大小为127 byte,加密后为128个byte;因此共有2个加密块,第一个127 byte第二个为1个byte
  int outputSize = cipher.getOutputSize(data.length);//获得加密块加密后块大小
  int leavedSize = data.length % blockSize;
  int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
  byte[] raw = new byte[outputSize * blocksSize];
  int i = 0;
  while (data.length - i * blockSize > 0) {
  if (data.length - i * blockSize > blockSize)
  cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
  else
  cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
  //这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
  
  i++;
  }
  return raw;
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  * 解密
  * @param key 解密的密钥
  * @param raw 已经加密的数据
  * @return 解密后的明文
  * @throws EncryptException
  */
  public static byte[] decrypt(Key key, byte[] raw) throws EncryptException {
  try {
  Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  cipher.init(cipher.DECRYPT_MODE, key);
  int blockSize = cipher.getBlockSize();
  ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
  int j = 0;
  
  while (raw.length - j * blockSize > 0) {
  bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
  j++;
  }
  return bout.toByteArray();
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  *
  * @param args
  * @throws Exception
  */
  public static void main(String[] args) throws Exception {
  File file = new File("test.html");
  FileInputStream in = new FileInputStream(file);
  ByteArrayOutputStream bout = new ByteArrayOutputStream();
  byte[] tmpbuf = new byte[1024];
  int count = 0;
  while ((count = in.read(tmpbuf)) != -1) {
  bout.write(tmpbuf, 0, count);
  tmpbuf = new byte[1024];
  }
  in.close();
  byte[] orgData = bout.toByteArray();
  KeyPair keyPair = RSAUtil.generateKeyPair();
  RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
  RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
  
  byte[] pubModBytes = pubKey.getModulus().toByteArray();
  byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
  byte[] priModBytes = priKey.getModulus().toByteArray();
  byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
  RSAPublicKey recoveryPubKey = RSAUtil.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
  RSAPrivateKey recoveryPriKey = RSAUtil.generateRSAPrivateKey(priModBytes,priPriExpBytes);
  
  byte[] raw = RSAUtil.encrypt(priKey, orgData);
  file = new File("encrypt_result.dat");
  OutputStream out = new FileOutputStream(file);
  out.write(raw);
  out.close();
  byte[] data = RSAUtil.decrypt(recoveryPubKey, raw);
  file = new File("decrypt_result.html");
  out = new FileOutputStream(file);
  out.write(data);
  out.flush();
  out.close();
  }
  }
  
  加密可以用公钥,解密用私钥;或者加密用私钥。通常非对称加密是非常消耗资源的,因此可以对大数据用对称加密如:des(具体代码可以看我以前发的贴子),而对其对称密钥进行非对称加密,这样既保证了数据的安全,还能保证效率。
posted @ 2008-09-19 17:15 小马歌 阅读(273) | 评论 (0)编辑 收藏
 
什么是RSA
  RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。
  RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。
  RSA的缺点主要有:A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048比特长的密钥,其他实体使用1024比特的密钥。
  这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
  RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
  RSA的算法涉及三个参数,n、e1、e2。
  其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。
  e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
  (n及e1),(n及e2)就是密钥对。
  RSA加解密的算法完全相同,设A为明文,B为密文,则:A=B^e1 mod n;B=A^e2 mod n;
  e1和e2可以互换使用,即:
  A=B^e2 mod n;B=A^e1 mod n;
一、RSA 的安全性
  RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解 RSA就一定需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。目前, RSA 的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。现在,人们已能分解多个十进制位的大素数。因此,模数n 必须选大一些,因具体适用情况而定。
二、RSA的速度
  由于进行的都是大数计算,使得RSA最快的情况也比DES慢上倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。
三、RSA的选择密文攻击
  RSA在选择密文攻击面前很脆弱。一般攻击者是将某一信息作一下伪装( Blind),让拥有私钥的实体签署。然后,经过计算就可得到它所想要的信息。实际上,攻击利用的都是同一个弱点,即存在这样一个事实:乘幂保留了输入的乘法结构:
  ( XM )^d = X^d *M^d mod n
  前面已经提到,这个固有的问题来自于公钥密码系统的最有用的特征--每个人都能使用公钥。但从算法上无法解决这一问题,主要措施有两条:一条是采用好的公钥协议,保证工作过程中实体不对其他实体任意产生的信息解密,不对自己一无所知的信息签名;另一条是决不对陌生人送来的随机文档签名,签名时首先使用One-Way HashFunction 对文档作HASH处理,或
四、RSA的公共模数攻击
  若系统中共有一个模数,只是不同的人拥有不同的e和d,系统将是危险的。最普遍的情况是同一信息用不同的公钥加密,这些公钥共模而且互质,那末该信息无需私钥就可得到恢复。设P为信息明文,两个加密密钥为e1和e2,公共模数是n,则:
  C1 = P^e1 mod n
  C2 = P^e2 mod n
  密码分析者知道n、e1、e2、C1和C2,就能得到P。
  因为e1和e2互质,故用Euclidean算法能找到r和s,满足:
  r * e1 + s * e2 = 1
  假设r为负数,需再用Euclidean算法计算C1^(-1),则
  ( C1^(-1) )^(-r) * C2^s = P mod n
  另外,还有其它几种利用公共模数攻击的方法。总之,如果知道给定模数的一对e和d,一是有利于攻击者分解模数,一是有利于攻击者计算出其它成对的e’和d’,而无需分解模数。解决办法只有一个,那就是不要共享模数n。
  RSA的小指数攻击。 有一种提高 RSA速度的建议是使公钥e取较小的值,这样会使加密变得易于实现,速度有
  所提高。但这样作是不安全的,对付办法就是e和d都取较大的值。
  RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。 RSA的缺点主要有:A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits 以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET( Secure Electronic Transaction )协议中要求CA采用比特长的密钥,其他实体使用比特的密钥。
posted @ 2008-09-19 17:15 小马歌 阅读(227) | 评论 (0)编辑 收藏
 

Java 程序中也有内存漏洞?当然有。与流行的观念相反,在 Java 编程中,内存治理仍然是需要考虑的问题。在本文中,您将了解到什么会导致内存漏洞以及何时应该关注这些漏洞。您还有机会实践一下在您自己的项目中解决漏洞问题。
  
  Java 程序中的内存漏洞是如何显现出来的
  大多数程序员都知道,使用像 Java 这样的编程语言的一大好处就是,他们不必再担心内存的分配和释放问题。您只须创建对象,当应用程序不再需要这些对象时,Java 会通过一种称为“垃圾收集”的机制将这些对象删除。这种处理意味着 Java 已经解决了困扰其他编程语言的烦人问题 -- 可怕的内存漏洞。是这样的吗?
  
  在深入讨论之前,我们先回顾一下垃圾收集的工作方式。垃圾收集器的工作是发现应用程序不再需要的对象,并在这些对象不再被访问或引用时将它们删除。垃圾收集器从根节点(在 Java 应用程序的整个生存周期内始终存在的那些类)开始,遍历被引用的所有节点进行清除。在它遍历这些节点的同时,它跟踪哪些对象当前正被引用着。任何类只要不再被引用,它就符合垃圾收集的条件。当删除这些对象以后,就可将它们所占用的内存资源返回给 Java 虚拟机 (JVM)。
  
  所以的确是这样,Java 代码不要求程序员负责内存的治理和清除,它会自动对无用的对象执行垃圾收集。但是,要紧记的一点是 仅当一个对象不再被引用时才会被统计为无用的。图 1 说明了这个概念。
  
 

  
图 1. 无用但仍被引用的对象

  
  上面说明了在 Java 应用程序执行期间具有不同生存周期的两个类。类 A 首先被实例化,并会在很长一段时间或程序的整个生存期内存在。在某个时候,类 B 被创建,类 A 添加对这个新创建的类的一个引用。现在,我们假定类 B 是某个用户界面小部件,它由用户显示甚至解除。假如没有清除类 A 对 B 的引用,则即便不再需要类 B,并且即便在执行下一个垃圾收集周期以后,类 B 仍将存在并占用内存空间。
  
  何时应该关注内存漏洞?
  假如您的程序在执行一段时间以后发出 java.lang.OutOfMemoryError 错误,则内存漏洞肯定是一个重大嫌疑。除了这种明显的情况之外,何时还应该关注内存漏洞呢?持完美主义观点的程序员肯定会回答,应该查找并纠正 所有内存漏洞。但是,在得出这个结论之前,还有几个方面需要考虑,包括程序的生存期和漏洞的大小。
  
  完全有这样的可能,垃圾收集器在应用程序的生存期内可能始终不会运行。不能保证 JVM 何时以及是否会调用垃圾收集器 -- 即便程序显式地调用 System.gc() 也是如此。通常,在当前的可用内存能够满足程序的内存需求时,JVM 不会自动运行垃圾收集器。当可用内存不能满足需求时,JVM 将首先尝试通过调用垃圾收集来释放出更多的可用内存。假如这种尝试仍然不能释放足够的资源,JVM 将从操作系统获取更多的内存,直至达到答应的最大极限。
  
  例如,考虑一个小型 Java 应用程序,它显示一些用于修改配置的简单用户界面元素,并且它有一个内存漏洞。很可能到应用程序关闭时也不会调用垃圾收集器,因为 JVM 很可能有足够的内存来创建程序所需的全部对象,而此后可用内存则所剩无几。因此,在这种情况下,即使某些“死”对象在程序执行时占用着内存,它实际上并没有什么用途。
  
  假如正在开发的 Java 代码要全天 24 小时在服务器上运行,则内存漏洞在此处的影响就比在我们的配置实用程序中的影响要大得多。在要长时间运行的某些代码中,即使最小的漏洞也会导致 JVM 耗尽全部可用内存。
  
  在相反的情况下,即便程序的生存期较短,假如存在分配大量临时对象(或者若干吞噬大量内存的对象)的任何 Java 代码,而且当不再需要这些对象时也没有取消对它们的引用,则仍然可能达到内存极限。
  
  最后一种情况是内存漏洞无关紧要。我们不应该认为 Java 内存漏洞像其他语言(如 C++)中的漏洞那样危险,在那些语言中内存将丢失,且永远不会被返回给操作系统。在 Java 应用程序中,我们使不需要的对象依附于操作系统为 JVM 所提供的内存资源。所以从理论上讲,一旦关闭 Java 应用程序及其 JVM,所分配的全部内存将被返回给操作系统。
  
  确定应用程序是否有内存漏洞
  为了查看在 Windows NT 平台上运行的某个 Java 应用程序是否有内存漏洞,您可能试图在应用程序运行时观察“任务治理器”中的内存设置。但是,在观察了运行中的几个 Java 应用程序以后,您会发现它们比本地应用程序占用的内存要多得多。我做过的一些 Java 项目要使用 10 到 20 MB 的系统内存才能启动。而操作系统自带的 Windows EXPlorer 程序只需 5 MB 左右的内存。
  
  在 Java 应用程序内存使用方面应注重的另一点是,这个典型程序在 IBM JDK 1.1.8 JVM 中运行时占用的系统内存越来越多。似乎直到为它分配非常多的物理内存以后它才开始向系统返回内存。这些情况是内存漏洞的征兆吗?
  
  要理解其中的缘由,我们必须熟悉 JVM 如何将系统内存用作它的堆。当运行 java.exe 时,您使用一定的选项来控制垃圾收集堆的起始大小和最大大小(分别用 -ms 和 -mx 表示)。Sun JDK 1.1.8 的默认起始设置为 1 MB,默认最大设置为 16 MB。IBM JDK 1.1.8 的默认最大设置为系统总物理内存大小的一半。这些内存设置对 JVM 在用尽内存时所执行的操作有直接影响。JVM 可能继续增大堆,而不等待一个垃圾收集周期的完成。
  
  这样,为了查找并最终消除内存漏洞,我们需要使用比任务监视实用程序更好的工具。当您试图调试内存漏洞时,内存调试程序(请参阅参考资源)可能派得上用场。这些程序通常会显示堆中的对象数、每个对象的实例数和这些对象所占用的内存等信息。此外,它们也可能提供有用的视图,这些视图可以显示每个对象的引用和引用者,以便您跟踪内存漏洞的来源。
  
  下面我将说明我是如何用 Sitraka Software 的 JProbedebugger 检测和去除内存漏洞的,以使您对这些工具的部署方式以及成功去除漏洞所需的过程有所了解。
  
  内存漏洞的一个示例
  本例集中讨论一个问题,我们部门当时正在开发一个商业发行版软件,这是一个 Java JDK 1.1.8 应用程序,一个测试人员花了几个小时研究这个程序才最终使这个问题显现出来。这个 Java 应用程序的基本代码和包是由几个不同的开发小组在不同的时间开发的。我猜想,该应用程序中意外出现的内存漏洞是由那些没有真正理解别人开发的代码的程序员造成的。
  
  我们正在讨论的 Java 代码答应用户为 Palm 个人数字助理创建应用程序,而不必编写任何 Palm OS 本地代码。通过使用图形用户界面,用户可以创建窗体,向窗体中添加控件,然后连接这些控件的事件来创建 Palm 应用程序。测试人员发现,随着不断创建和删除窗体和控件,这个 Java 应用程序最终会耗尽内存。开发人员没有检测到这个问题,因为他们的机器有更多的物理内存。
  
  为了研究这个问题,我用 JProbe 来确定什么地方出了差错。尽管用了 JProbe 所提供的强大工具和内存快照,研究仍然是一个冗长乏味、不断重复的过程,首先要确定出现内存漏洞的原因,然后修改代码,最后还得检验结果。
  
  JProbe 提供几个选项,用来控制调试期间实际记录哪些信息。经过几次试验以后,我断定获取所需信息的最有效方法是,关闭性能数据收集,而将注重力集中在所捕捉的堆数据上。JProbe 提供了一个称为 Runtime Heap Summary 的视图,它显示 Java 应用程序运行时所占用的堆内存量随时间的变化。它还提供了一个工具栏按钮,必要时可以强制 JVM 执行垃圾收集。假如您试图弄清楚,当 Java 应用程序不再需要给定的类实例时,这个实例会不会被作为垃圾收集,这个功能将很有用。图 2 显示了使用中的堆存储量随时间的变化。
  
 

  
图 2. Runtime Heap Summary

  
  在 Heap Usage Chart 中,蓝色部分表明已分配的堆空间大小。在启动这个 Java 程序并达到稳定状态以后,我强制垃圾收集器运行,在图中的表现就是绿线(这条线表明插入了一个检查点)左侧的蓝线的骤降。随后,我添加了四个窗体,然后又将它们删除,并再次调用了垃圾收集器。当程序返回仅有一个可视窗体的初始状态时,检查点之后的蓝色区域高于检查点之前的蓝色区域这一情况表明可能存在内存漏洞。我通过查看 Instance Summary 证实确实有一个漏洞,因为 Instance Summary 表明 FormFrame 类(它是窗体的主用户界面类)的计数在检查点之后增加了 4。
  
  查找原因
  为了将测试人员报告的问题剔出,我采取的第一个步骤是找出几个简单的、可重复的测试案例。就本例而言,我发现只须添加一个窗体,将它删除,然后强制执行垃圾收集,结果就会导致与被删除窗体相关联的许多类实例仍然处于活动状态。这个问题在 JProbe 的 Instance Summary 视图中很明显,这个视图统计每个 Java 类在堆中的实例数。
  
  为了查明使垃圾收集器无法正常完成其工作的那些引用,我使用 JProbe 的 Reference Graph(如图 3 所示)来确定哪些类仍然引用着目前未被删除的 FormFrame 类。在调试这个问题时该过程是最复杂的过程之一,因为我发现许多不同的对象仍然引用着这个无用的对象。用来查明究竟是哪个引用者真正造成这个问题的试错过程相当耗时。
  
  在本例中,一个根类(左上角用红色标明的那个类)是问题的发源地。右侧用蓝色突出显示的类处在从最初的 FormFrame 类跟踪而来的路径上。
  


  
图 3. 在引

资料引用:http://www.knowsky.com/365325.html

posted @ 2008-09-19 17:10 小马歌 阅读(258) | 评论 (0)编辑 收藏
 
动态口令,也被成为一次性口令(OTP,One-Time password)
  OTP试图解决用户选择强壮密码时的一些问题。大多数OTP基于双要素认证原则运行。要认证一个系统,你需要拥有一个令牌卡和你的个人识别码(PIN personal identification number)。生成和同步密码的方法随OTP系统的不同而不同。在一种比较流行的OTP方法中,令牌卡在一个时间间隔内(通常为 60S)生成登陆密码。这个看上去随机的数字串实际上与OTP服务器和令牌上运行的数学算法紧密相关。一个由令牌生成的登录密码可能类似这样:4F40D974。PIN要么与算法一起使用生成登录密码(随后变成OTP),要么与登陆密码一起使用。
  使用由算法和PIN生成登录密码的系统防止个人反复嗅探网络后获得用户的PIN。OTP用以下方法改进了密码:
  >用户再也不能选择弱密码
  >用户只要记住PIN,而不用记住传统的强密码
  > 一旦密码被使用一次,线路上嗅探到的密码就已经失效
  当然没有大面积的密码系统使用OTP是有原因的,OTP也有一些缺点:
  > 用户需要拥有令牌卡进行认证
  >OTP需要一台额外的服务器接受来自认证服务器中继的请求
  >使用OTP输入一个密码比输入一个用户需要记住的密码时间花费更高
  > 在大型网络中OTP价格不菲
  当考虑OTP总体评价时,它显然是一种有价值的技术,只是不能到处使用。大多数的机构选择将OTP用于他们安全策略中的关键系统,或用在密码破解尝试较多的地方。对于一个典型的机构,该地方以为着是财务和人力资源系统,也可以是拨号或虚拟专用网这样的远程系统。
  动态口令,又叫动态令牌、动态密码。它的主要原理是:用户登录前,依据用户私人身份信息,并引入随机数产生随机变化的口令,使每次登录过程中传送的口令信息都不同,以提高登录过程中用户身份认证的安全性。
  由于口令每次都变化,即使得到密码也没用,而且这种动态口令由专用算法生成,随机性高,不太容易被破解。因此,动态口令极大地提高了用户身份认证的安全性。
posted @ 2008-09-19 17:07 小马歌 阅读(1206) | 评论 (0)编辑 收藏
 
在上两讲中,笔者介绍了DirectShow的应用原理以及开发Filter之前的一些预备知识。这一讲,笔者就要手把手教你如何写自己的Filter啦。
首先,从VC++的项目开始(请确认你已经给VC++配置好了DirectX的开发环境)。写自己的Filter,第一步是使用VC++建立一个Filter的项目。由于DirectX SDK提供了很多Filter的例子项目(位于DXSDK\samples\Multimedia\DirectShow\ Filters目录下),最简单的方法就是拷贝一个,然后再在此基础上修改。但如果你是Filter开发的初学者,笔者并不赞成这么做。
自己新建一个Filter项目也很简单。使用VC++的向导,建立一个空的”Win32 Dynamic-link Library”项目。注意,几个文件是必须有的:.def文件,定义四个导出函数;定义Filter类的.cpp文件和.h文件,并在.cpp文件中定义Filter的注册信息以及两个Filter的注册函数:DllRegisterServer和DllUnregisterServer。(注:Filter的注册信息是Filter在注册时写到注册表里的内容,格式可以参考SDK的示例代码,Filter相关的GUID务必使用GuidGen.exe产生。)接下去进行项目的设置(Project->Settings…)。此时,你可以打开一个SDK的例子项目进行对比,有些宏定义完全可以照抄,最后注意将输出文件的扩展名改为.ax。
上一讲曾经提到过,在写Filter之前,选择一个合适的Filter基类是至关重要的。为此,你必须对几个Filter的基类有相当的了解。在实际应用中,Filter的基类并不总是选择CBaseFilter的。相反,因为我们绝大部分写的都是中间的传输Filter(Transform Filter),所以基类选择CTransformFilter和CTransInPlaceFilter的居多。如果我们写的是源Filter,我们可以选择CSource作为基类;如果是Renderer Filter,可以选择CBaseRenderer或CBaseVideoRenderer等。
总之,选择好Filter的基类是很重要的。当然,选择Filter的基类也是很灵活的,没有绝对的标准。能够通过CTransformFilter实现的Filter当然也能从CBaseFilter一步一步实现。下面,笔者就从本人的实际经验出发,对Filter基类的选择提出几点建议供大家参考。
首先,你必须明确这个Filter要完成什么样的功能,即要对Filter项目进行需求分析。请尽量保持Filter实现的功能的单一性。如果必要的话,你可以将需求分解,由两个(或者更多的)功能单一的Filter去实现总的功能需求。
其次,你应该明确这个Filter大致在整个Filter Graph的位置,这个Filter的输入是什么数据,输出是什么数据,有几个输入Pin、几个输出Pin等等。你可以画出这个Filter的草图。弄清这一点十分重要,这将直接决定你使用哪种“模型”的Filter。比如,如果Filter仅有一个输入Pin和一个输出Pin,而且一进一处的媒体类型相同,则一般采用CTransInPlaceFilter作为Filter的基类;如果媒体类型不一样,则一般选择CTransformFilter作为基类。
再者,考虑一些数据传输、处理的特殊性要求。比如Filter的输入和输出的Sample并不是一一对应的,这就一般要在输入Pin上进行数据的缓存,而在输出Pin上使用专门的线程进行数据处理。这种情况下,Filter的基类选择CSource为宜(虽然这个Filter并不是源Filter)。
当Filter的基类选定了之后,Pin的基类也就相应选定了。接下去,就是Filter和Pin上的代码实现了。有一点需要注意的是,从软件设计的角度上来说,应该将你的逻辑类代码同Filter的代码分开。下面,我们一起来看一下输入Pin的实现。你需要实现基类所有的纯虚函数,比如CheckMediaType等。在CheckMediaType内,你可以对媒体类型进行检验,看是否是你期望的那种。因为大部分Filter采用的是推模式传输数据,所以在输入Pin上一般都实现了Receive方法。有的基类里面已经实现了Receive,而在Filter类上留一个纯虚函数供用户重载进行数据处理。这种情况下一般是无需重载Receive方法的,除非基类的实现不符合你的实际要求。而如果你重载了Receive方法,一般会同时重载以下三个函数EndOfStream、BeginFlush和EndFlush。我们再来看一下输出Pin的实现。一般情况下,你要实现基类所有的纯虚函数,除了CheckMediaType进行媒体类型检查外,一般还有DecideBufferSize以决定Sample使用内存的大小,GetMediaType提供支持的媒体类型。最后,我们看一下Filter类的实现。首先当然也要实现基类的所有纯虚函数。除此之外,Filter还要实现CreateInstance以提供COM的入口,实现NonDelegatingQueryInterface以暴露支持的接口。如果我们创建了自定义的输入、输出Pin,一般我们还要重载GetPinCount和GetPin两个函数。
Filter框架的实现大致就是这样。你或许还想知道怎样在Filter上实现一个自定义的接口,以及怎么实现Filter的属性页等等。限于篇幅,笔者就不展开阐述了。其实,这些问题都能在SDK的示例项目中找到答案。其他的,关于在实际编程中应该注意的一些问题,笔者整理了一下,供大家参考。
1.    锁(Lock)问题
DirectShow应用程序至少包含有两条线程:一条主线程和一条数据传输线程。既然是多线程,肯定会碰到线程同步的问题。Filter有两种锁:Filter对象锁和数据流锁。Filter对象锁用于Filter级别的如Filter状态转换、BeginFlush、EndFlush等;数据流锁用于数据处理线程内,比如Receive、EndOfStream等。如果这两种锁没有搞清楚,很容易产生程序的死锁,这一点特别需要提醒。
2.    EndOfStream问题
当Filter接收到这个“消息”,意味着上一级Filter的数据都已经发送完毕。在这之后,如果Receive再有数据接收,也不应该去理睬它。如果Filter对输入Pin上的数据进行了缓存,在接收到EndOfStream后应确保所有缓存的数据都已经处理过了才能返回。
3.    Media Seeking问题
一般情况下,你只需要在Filter的输出Pin上实现NonDelegatingQueryInterface方法,当用户申请得到IID_ImediaPosition接口或IID_IMediaSeeking接口时将请求往上一级Filter的输出Pin上传递。当Filter Graph进行Mediaseeking的时候,一般会调用Filter上的BeginFlush、EndFlush和NewSegment。如果你的Filter对数据进行了缓存,你就要重载它们,并做出相应的处理。如果你的Filter负责给发送出去的Sample打时间戳,那么,在Mediaseeking之后应该重新从零开始打起。
4.    关于使用专门的线程
如果你使用了专门的线程进行数据的处理和发送,你需要特别小心,不要让线程进行死循环,并且要让线程处理函数能够去时时检查线程命令。应该确保在Filter结束工作的时候,线程也能正常地结束。有时候,你把GraphEdit程序关掉,但GraphEdit进程仍在内存中,往往就是因为数据线程没有安全关闭这个原因。
5.    如何从媒体类型中获取信息
比如,你想在输入Pin连接的媒体类型中,获取视频图像的宽、高等信息,你应该在输入Pin的CompleteConnect方法中实现,而不要在SetMediaType中。
posted @ 2008-09-19 15:07 小马歌 阅读(520) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 79 80 81 82 83 84 85 86 87 下一页 Last