5.3 系统登录.htm
来自「Windows2000后台服务程序开发手册」· HTM 代码 · 共 425 行 · 第 1/3 页
HTM
425 行
<TBODY style="LINE-HEIGHT: 25px">
<TR style="LINE-HEIGHT: 25px">
<TD style="LINE-HEIGHT: 25px" align=middle><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial
color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 列表5-1 </B></FONT>RegScan范例应用程序</FONT></TD></TR></TBODY></TABLE>
<CENTER></CENTER></A><A style="LINE-HEIGHT: 25px" name=205005>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e70d7
size=5><B style="LINE-HEIGHT: 25px">在系统登录中储存资料<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在讨论如何在系统登录中储存资料前,让我们先复习关于登录的适当用法之主题。如您所知,系统登录是一个被分享的资源。就其本身而言,它是受限制并且必须经由序列化(serialized)来存取它。您的应用程序可以在登录中储存许多MB之不同资料型别资料,但是在您的应用程序里最好不要将这些能力用到最大。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当在考虑登录的储存时,您应该问您自己二个问题:</FONT></P><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2>
<UL style="LINE-HEIGHT: 25px">
<LI
style="LINE-HEIGHT: 25px">这个资料是要储存我的应用程序之结构资讯部份,或者是一般的应用程序资料?(例如,它会不适当的将一个文字处理器的文件储在登录中)。<BR
style="LINE-HEIGHT: 25px">
<LI
style="LINE-HEIGHT: 25px">我所储存之资料数量大到(而且足够我经常存取此资料)能使得资料储存在文件中比储存在登录里更有效吗?(例如,一个经由文字处理器之应用程序所使用的拼字检查字典若是储存在文件里是比较好的)。<BR
style="LINE-HEIGHT: 25px"> </LI></UL></FONT>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在产生您的决定时,您会在文件系统的杂乱与在系统登录中无效率地储存大量的资料间权衡其利弊。后续的〈有效地使用系统登录〉一节中将更进一步讨论有效的使用系统登录部份。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您可以使用RegSetValueEx函数去储存资料至登录中。以下是它的函数原型:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">LONG RegSetValueEx( <BR> HKEY hkey, <BR> PCTSTR pszValueName, <BR> DWORD dwReserved, <BR> DWORD dwType, <BR> CONST BYTE *pbData, <BR> DWORD cbData);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>hkey参数参考到被储存之登录值里的机码。pszValueName是您想要使用的登录值之名称。如果您传递NULL或是一个指向空字串的指标给pszValueName,系统会在机码的预设登录值中储存您的资料。dwType参数应该依据您在此登录值中储存的资料型别而被设定为表格5-2所列之资料型别值之一。pbData
参数指向在登录中实际被储存的资料。在cbData参数中,您应以位元组为单位传递资料的大小。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如果RegSetValueEx执行成功,它会回传ERROR_SUCCESS。以下的程序代码说明了经由一个称为RegSetStringValue之函数包装RegSetValueEx的使用方法:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">LONG RegSetStringValue(HKEY hkey,PCTSTR pszValueName, <BR> PCTSTR pszString){ <BR> //取得字串的长度 <BR> int nDataSize =lstrlen(pszString); <BR> //加入一个结束字元的位置 <BR> nDataSize++; <BR> //依字元大小相乘 <BR> nDataSize =nDataSize *sizeof(TCHAR); <BR> //试图去储存资料至登录中 <BR> return(RegSetValueEx(hkey,pszValueName,0,REG_SZ, <BR> (PBYTE)pszString,nDataSize)); <BR>}</PRE></FONT></DIV>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>Shell登录函数包含了一个称为SHSetValue的函数,与SHGetValue一样,在一开始不要求您的应用程序从一个机码中取得handle。SHSetValue函数被定义如下:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">DWORD SHSetValue( <BR> HKEY hkey, <BR> PCTSTR pszSubKey, <BR> PCTSTR pszValue, <BR> PDWORD pdwType, <BR> PVOID pvData, <BR> PDWORD pcbData);</PRE></FONT></DIV>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如表格5-2所示,登录支援了许多资料型别,您可以依您的应用程序所需而选择型别。您将会发现自己经常使用REG_DWORD、REG_SZ与REG_BINARY。一个应用程序会使用REG_DWORD来储存数字的设定,用REG_SZ(或REG_MULTI_SZ)来储存文字设定,而REG_BINARY则储存其他没有相符的登录型别之资料。当在使用REG_BINARY型别时,一般的登录工具像RegEdt32,并不知道如何去展示除了位元组区块之登录值以外的资料。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在继续之前,我想要澄清二个可能会令人困惑的登录型别:当REG_EXPAND_ SZ和REG_MULTI_SZ. The
REG_EXPAND_SZ。在它是一个被储存在登录中的零终止Unicode或ANSI字串的情形下,REG_EXPAND_SZ登录型别会与REG_SZ型别很类似。它们的不同之处是,在惯例上通常会在将储存于REG_EXPAND_SZ的值从登录取出后再传递给ExpandEnvironmentStrings函数。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>登录函数不会自动地展开REG_EXPAND_SZ型别之登录值中的资料。您的应用程序应负起传递该字串至ExpandEnvironment
Strings的责任。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>这里是ExpandEnvironmentStrings的函数原型:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">DWORD ExpandEnvironmentStrings( <BR> PCTSTR pszSrc, <BR> PTSTR pszDst, <BR> DWORD nSize);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>因为文件中的说明使得REG_MULTI_SZ被大大地误解。文件声明一个REG_MULTI_SZ值是「一个被二个零字元终止之零终止字串阵列」。我认为此文件应该被解读成:「一个REG_MULTI_SZ值以一个连续的零终止字串之形式而被储存,并有二个零字元终止了最后的字串」。记得当您在储存或取回此型别的资料时,您的缓冲区大小必须也包含了所有用于终止的零字元,并在最后多加上一个零。图5-3显示了一个由叁个字串组成之多零终止字串(multizero-terminated)登录值的范例。</FONT></P>
<P><BR style="LINE-HEIGHT: 25px"> </P>
<CENTER style="LINE-HEIGHT: 25px">
<P><INPUT id=3 style="LINE-HEIGHT: 25px" type=image height=37
width=502 src="5.3 系统登录.files/5-3.gif" border=0
onclick="imgclick"></P></CENTER>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE style="LINE-HEIGHT: 25px" border=0>
<TBODY style="LINE-HEIGHT: 25px">
<TR style="LINE-HEIGHT: 25px">
<TD style="LINE-HEIGHT: 25px" align=middle><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial
color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 图5-3 </B></FONT>一个由叁个字串组成的多零终止字串登录值</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>范例中的资料显示了叁个字「Jason’s」、「Test」以及「MULTI_SZ」,它们就像是个别分开的字串一样。缓冲区将会被要求以ANSI形式保留23个位元组以及以Unicode的形式保留46个位元组给此资料。</FONT></P></A><A
style="LINE-HEIGHT: 25px" name=205006>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e70d7
size=5><B style="LINE-HEIGHT: 25px">远端存取登录<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>Windows允许您在一个远端的机器上使用与您在本端机器存取登录相同的方法去存取登录的内容。这使得在开发一个可以从网路上的远端位置设定软件的工作变得更容易。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>为了考虑直接在Windows下给予远端的登录存取,需要钻研至安全的部份。我将安全性部份的讨论内容延后到第十章再详细说明。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>Windows登录函数的设计者实际上已经由允许应用程序开发者使用与他们用来存取本机登录相同的函数来简化远端存取登录的工作。例如,您可以使用RegOpenKeyEx去开启在远端机器与本地端机器上的机码。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>同样地,RegSetValueEx、RegQueryValueEx、RegEnumKey等函数皆可被用来操作一个远端机器上的登录。唯一的不同是取得对远端机器上的系统事先定义登录机码之一的handle。这可以经由呼叫RegConnectRegistry来完成,它的函数原型如下:</FONT></P></A><A
style="LINE-HEIGHT: 25px" name=231_1>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">LONG RegConnectRegistry( <BR> PTSTR pszMachineName, <BR> HKEY hkey, <BR> PHKEY phkResult);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如您所见,RegConnectRegistry函数相当容易。传递想要连接的机器名称至pszMachineName参数中,您也可以传递一个事先定义之登录机码(例如HKEY_LOCAL_MACHINE或HKEY_USERS)以指示您想要存取的远端机器之登录部份。最后,您要提供RegConnectRegistry一个在储存一个开启的handle至远端登录的根机码函数内指向HKEY变数的指标。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在您的应用程序中可以传递NULL给pszMachineName参数以指示一个与本地端机器的连结。这是在使用最小的附加逻辑而建立在远端或本地工作之登录工具时的一个方便机制。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>为了从一个远端登录中取回登录值,您可以使用RegQueryMultipleValues函数。此函数与RegQueryValueEx类似,只是它可以要求由许多部份组成的值。RegQueryMultipleValues函数允许您的应用程序经由一个单一的网路操作而要求由许多部份组成的值,以将网路流量最小化。RegQueryMultipleValues并不是专门用在远端登录的操作中,只是它实际上较常被使用在此而已。在十分需要网路频?的企业中,每一个网路的碰撞皆是成本的一部份。以下为RegQueryMultipleValues的函数原型:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">LONG RegQueryMultipleValues( <BR> HKEY hkey, <BR> PVALENT val_list, <BR> DWORD num_vals, <BR> PTSTR pszValueBuf, <BR> PDWORD dwTotsize);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您的应用程序必须经由val_list参数来传递一个VALENT结构的阵列至函数中。系统接着会使用此阵列来寻找被取回的值,以及存放在包含每一个登录值资讯的结构。以下为VALENT结构的宣告内容:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">typedef struct value_ent { <BR> PTSTR ve_valuename; <BR> DWORD ve_valuelen; <BR> DWORD ve_valueptr; <BR> DWORD ve_type; <BR> }VALENT;</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>它很奇特,登录函数的设计者也不会去依照单一操作的方法而实作一个在登录内设定多个值的函数。因为登录通常被读取的机会比被写入多,所以我假设它并没有被完成。当然,您可以经由建立多个对RegSetValueEx的呼叫而实作属于您自己的「RegSe-MultipleValues」。然而,使用这个函数的实作并不会减少网路流量。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>RegQueryMultipleValues函数被限制每一次呼叫皆不能读取超过1MB的资料。只有在它能回传所有被要求的值时,该函数才会执行成功。如果被要求的资料皆超过1MB,它会失败。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
</A><A style="LINE-HEIGHT: 25px" name=205007>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e70d7
size=5><B style="LINE-HEIGHT: 25px">有效地使用系统登录<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>现在您已经知道让您在系统登录中操作资料的特征,所以您可以开始学习如何在您的服务应用程序里建立这些特征。登录应该充当您的服务结构资讯之贮藏处,但是在某些方面,它也会充当一个让管理者用来把结构需求通知服务器的一个机制。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>大部份的服务器上皆已实作了许多服务,而这些服务没有可显示的使用者介面。事实上,不管用来发展一个服务器的处理程序为何,它们皆有充份的理由可以把一个使用者介面从您的服务器排除。当您排除了使用者介面时,您通常会建立另外一个容易管理的应用程序来设定您的服务。此应用程序可以在登录中储存那些可被您的服务读取的结构资讯。管理的应用程序应该能在远端或本地执行,而且也能够在Microsoft
Windows 95或Window 98上执行。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您在设计您的服务与管理应用程序时,您应该依照一些重要的规则以建立一个最有效之使用系统登录方法。</FONT></P><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?