I. Sơ lược về Registry
Registry là nơi lưu trữ tất cả các các loại cấu trúc dữ liệu. Cấu hình hệ thống Windows, cấu hình phần cứng máy tính, cấu hình thông tin về các chương trình ứng dụng dựa trên Win32, và các thiết lập người dùng khác đều được lưu trong Registry.
Ví dụ, bất cứ một phần cứng máy tính nào thay đổi đều làm chức năng Plug and Play (Cắm và chạy) khởi tạo ngay và làm thay đổi luôn cấu hình trong Registry.
Registry lưu trữ tất cả các thiết lập về cấu trúc bộ nhớ, phần cứng, thiết bị ngoại vi, và các thành phần liên quan đến mạng. Bạn sẽ tìm thấy ở đó nhiều hơn những thiết lập cần thiết trong các tệp khởi tạo ban đầu
Từ Win98 về sau, Windows có sử dụng Registry Checker để tự quét Registry, nếu không thấy gì, nó tự lưu backup một lần trong ngày, nếu tìm thấy lỗi sẽ sửa... có thể sửa bằng cách thay thế bản Registry đã backup gần nhất còn tốt. Registry Checker tối ưu hoá và nén file backup thành công mỗi lần khởi động máy. Nó còn làm một loạt các việc linh tinh như loại bỏ những khoảng trống không dùng trong Registry, tối ưu hoá...
Các tệp Registry của Windows.
Registry hiện tại bao gồm 3 tệp chính:
1. Tệp USER.DAT
Dùng để lưu trữ những xác lập người sử dụng đối với các phần mềm.
2. Tệp SYSTEM.DAT
Dùng để lưu trữ những xác lập liên quan tới máy tính và phần cứng.
3. Tệp Policy.pol
System policies được thiết kế để chuẩn bị cho việc ghi đè bất cứ thiết lập đã được chứa trong 2 thành phần registry khác nhau.
System policies có thể chứa dữ liệu bổ sung đặc trưng tới mạng hay môi trường tổ hợp như đã được cài đặt bởi network administrator. Bản thân System policies cũng đã được chứa trong tệp Policy.pol. Không như SYSTEM.DAT và USER.DAT, Policy.pol không phải là thành phần bắt buộc của phần cài đặt Windows.
Lời khuyên của Microsoft về những công cụ xử lý registry
Phương pháp | Thiết lập |
Control Panel | Phần lớn thiết lập hệ thống SYSTEM. Ví dụ bạn sử dụng Display Properties để sửa các thành phần của mục appearance |
System Policy Editor | Thiết lập người dùng, vài thiết lập hệ thống. |
Các chương trình tiện ích thứ 3 | Thiết lập chi tiết ứng dụng |
Bạn có thể đã sử dụng Registry Editor để thay đổi Registry bằng tay. Tôi thường dùng Norton Registry Editor vì nó còn có thêm chức năng khác, ví dụ như tìm và thay thế đối với các thành phần của Registry.
Từ các phần mềm Registry Editor trên, ta nhận thấy registry được bố trí thành các nhánh lớn. Tại mỗi nhánh có các khoá SUBKEY. Tại các SUBKEY dữ liệu được lưu ở các dạng:
1. String (Dạng chuỗi)
2. Numeric (Dạng số)
3. Binary (Dạng nhị phân)
4. Expanded String (Dạng chuỗi mở rộng)
5. MultiString (Dạng chuỗi tổng hợp)
(Nếu bạn dùng Registry Editor - REGEDIT. EXE thì sẽ gọi tên khác là DWORD)
Ta hãy nghiên cứu sơ đồ mà Microsoft vẽ (Từ đĩa MSDN) về Registry:
Nhìn sơ đồ ta nhận thấy:
Nếu môi trường Windows là sân khấu thì Registry giống như một cuốn sổ tay của đạo diễn. Trong đó các thiết lập liên quan đến phần cứng thì hầu như không thay đổi (Nếu ta không thay phần cứng để phần đề tếch của Windows nhận ra). Nếu thay đổi phần cứng, phần đề tếch này sẽ bắt bạn phải đổi mã điều khiển đối với từng thiết bị.
Xin nói thêm phần này kỹ hơn một chút vì tôi nhận được rất nhiều thư hỏi của các bạn về những vấn đề liên quan đến phần cứng và DRIVER. Một số đông bạn chưa hiểu rõ cách thức làm việc của Windows nên ngay cả những lỗi rất đơn giản như màn hình chỉ có 16 màu (Không chọn được 256 màu hay cao hơn như High Color, True Color) cũng không biết cách giải quyết.
Khi máy tính của bạn có những thiết bị gì, hệ điều hành Windows khi cài đặt hoặc khi đề tếch thiết bị nó sẽ yêu cầu bạn phải đưa ra các tệp DRIVER của thiết bị đó. DRIVER là gì ư? Ồ! Nó chỉ là tệp mã điều khiển thiết bị. Giống như sơ đồ công tắc của thiết bị nào đó. Khi máy tính có công việc liên quan đến điều khiển thiết bị, hệ điều hành Windows sẽ tra trong Registry xem tệp mã nó là tệp nào. Tệp mã sẽ được nạp vào RAM một phần hay toàn bộ, ở một vị trí nào đó. Căn cứ vào lệnh đưa tới từ chương trình, Hệ điều hành sẽ đưa lệnh tới địa chỉ phần mã điều khiển này. Phần mã điều khiển sẽ chỉ tiếp cho con trỏ tới vị trí của lệnh cần thực hiện năm trong phần mã, tương ứng với mã lệnh đưa tới. Khi đó công việc được thực hiện chính xác vì phần mã đúng với thiết bị.
Nếu thiết bị một kiểu, mã DRIVER khác với kiểu được lắp vào máy, thì chẳng khác gì bạn đưa ra một sơ đồ máy khác với máy đang sử dụng. Khi đó sẽ có xung đột, trường hợp này Windows sẽ tự chuyển sang chức năng Đờ phôn ngầm định đối với các khoá, và như vậy bạn sẽ thấy Windows không thể hiện đúng với thực tế của mình. Bạn có thể vào Control Panel chọn mục System để kiểm tra, nếu thấy dấu ? cạnh tên mã thiết bị phần nào thì chọn Update để đổi mã.
Các khoá về mã phần cứng đều được lưu trong tệp SYSTEM.DAT. Do phần này ít thay đổi, vả lại chức năng Plug and Play của Windows quá siêu, nên ta sẽ tạm gác nghiên cứu đến phần này. Sau này tôi sẽ đề nghị một chương trình khoá thiết bị bằng phần mềm ở những chương sau.
Các khoá về phần mềm thường là lưu trữ các thiết lập Option... của từng phần mềm ứng dụng riêng. Ta có thể nhận ra, trước đây khi sử dụng Win 3.1 về trước, các thiết lập này được lưu trên đĩa bằng các tệp đuôi INI. Do Win32 khác xa về cấu trúc, nếu dùng các tệp INI sẽ tương đối bất tiện, ví dụ thực tế dung lượng bỏ phí trên đĩa cực lớn, nên Microsoft đã tích hợp vào các tệp Registry. Tuy nhiên, các tệp WIN.INI, SYSTEM.INI vẫn còn được sử dụng để có thể làm việc với các ứng dụng cũ.
Các khoá "mềm" có thể thay đổi thường xuyên khi ta sử dụng chức năng options để đặt lại. Ta nen lựa chọn tối ưu chứ đừng thí nghiệm vì sẽ có nhiều lỗi không đáng có. Bộ Norton Utilities có nhiều chức năng trong đó có Optimization Wizard (Tối ưu hoá) cũng sắp xếp và tổ chức lại Registry. WinDoctor và System Check thường kiểm tra sai sót hoặc thừa trong Registry để xử lý. Nếu bạn biết chút ít tiếng Anh, thì đó là công cụ thuận tiện đối với bạn.
2. Lập trình với Registry
Khi lập trình đối với Registry, bạn phải thực hiện hết sức thận trọng, sao lưu các tệp này thường xuyên để tránh lỗi đáng tiếc, phải mất công cài lại thì cũng rất mất thời gian.Sử dụng các hàm API đối với Registry cũng xin hết sức thận trọng. Tôi đưa ra một ví dụ để bạn có thể nghiên cứu rõ hơn. Đó là lập trình với Win API chính trong VBA. Ví dụ này sử dụng cách thiết đặt các tham số của WINWORD. Bạn có thể căn cứ vào đây để viết ra các ứng dụng khác tương tự. Phần này bạn chỉ việc copy phần lập trình để nghiên cứu và chạy thử.
2.1 Tạo Form
Để tạo Macro bạn hãy tạo Form tương tự như sau:
'Form thứ nhất
(Name)=EditCnvOptionsForm
Caption=Các lựa chọn sửa chữa Conversions
'Nhãn 1
(Name)=lblConversion
Caption= Conversion:
'Nhãn2
(Name)=lblCnvOption
Caption= Lựa chọn:
'Nhãn 3
(Name)=lblSetting
Caption= Thiết lập:
'Các hộp bỏ trống:
(Name)=cboConverters
(Name)=lstOptions
(Name)=txtSetting
(Name)=OptYes
(Name)=OptNo
'Các nút lệnh tuỳ ý Caption
(Name) =cmdSet
(Name) =cmdOK
(Name) =cmdHelp
'Viết lệnh cho Form thứ nhất:
'----------------------------------------------------
'--- Khởi tạo combo box với tên conveter ---
'----------------------------------------------------
Public Function ControlsInit() As Boolean
' Lấp đầy combo với đoạn text converters và graphics filters
ListConverters hCnvExpKeyHandle, HKEY_LOCAL_MACHINE, _
strREG_TEXT_CNV_EXPORT, strREG_CNV_NAME
ListConverters hCnvImpKeyHandle, HKEY_LOCAL_MACHINE, _
strREG_TEXT_CNV_IMPORT, strREG_CNV_NAME
ListConverters hFltExpKeyHandle, HKEY_LOCAL_MACHINE, _
strREG_GRAPH_FLT_EXPORT, strREG_CNV_NAME
ListConverters hFltImpKeyHandle, HKEY_LOCAL_MACHINE, _
strREG_GRAPH_FLT_IMPORT, strREG_CNV_NAME
' có bất cứ dữ liệu nào được đọc từ registry?
If clsCnvTable.ConverterCount = 0 Then
ControlsInit = False
Exit Function
End If
' lấp đầy combo box với tên converter names
clsCnvTable.AddConverterNamesToCombo cboConverters
' Chọn converter đầu tiên trên combo
cboConverters.ListIndex = 0
ControlsInit = True
End Function
Private Sub CommitChange(ByVal strNewString As String)
Dim strValue As String
Dim hHandleOptKey As Long
Dim res&
Dim strTemp As String
Dim i As Integer
' Nếu chọn phần trên list box khác
If ExtractOptionData(lstOptions.Value) <> strNewString Then
' triển khai chuỗi Value string
strValue = ExtractOptionValue(lstOptions.Value)
' Tìm khoá key handle của converter trên combo
hHandleOptKey = clsCnvTable.OptionsHandle(cboConverters.Value)
' Viết chuỗi dữ liệu mới Data string vào registry
res& = RegSetValueExString(hHandleOptKey, strValue, 0&, REG_SZ, _
strNewString, Len(strNewString))
If res& <> ERROR_SUCCESS Then
GoTo FatalError
End If
' Cập nhật lựa chọn vào list box
i = lstOptions.ListIndex
lstOptions.RemoveItem i ' bỏ cũ
lstOptions.AddItem strValue & strEQUALS_SIGN & strNewString, i ' Thêm mới
lstOptions.ListIndex = i ' chiếu sáng trùng
End If
Exit Sub
FatalError:
ReportRegError res&
End Sub
'-----------------------------------------
' Khai triển dữ liệu conversion option data
' Từ chuỗi định dạng "Option=Data"
'-----------------------------------------
Private Function ExtractOptionData(ByVal strDummy) As String
' Khai triển từng dòng sau khi bị biến thành 0
ExtractOptionData = Right$(strDummy, _
Len(strDummy) - InStr(strDummy, strEQUALS_SIGN))
End Function
'-----------------------------------------
' Khai triển giá trị lựa chọn conversion
' từ chuỗi định dạng "Option=Data"
'-----------------------------------------
Private Function ExtractOptionValue(ByVal strDummy As String) As String
' Khai triển từng dòng sau khi bằng 0
ExtractOptionValue = Left$(strDummy, InStr(strDummy, strEQUALS_SIGN) - 1)
End Function
'----------------------------------------------------------
' Liệt kê tất cả registered text converters và graphics filters
'----------------------------------------------------------
Private Sub ListConverters(keyHandleDummy As Long, _
ByVal lPredefRegKey As Long, _
ByVal strConverterDir As String, _
ByVal strWhatImLookingFor As String)
' Vị trí
Dim subKeyHandle&
Dim subSubKeyHandle&
Dim strKeyName$, strClassName$
Dim keyLen&, classLen&
Dim res&
Dim i%
' Nháp RegEnumKeyEx temps
Dim subKey As String * MAX_TEXT_BUFF ' tên converter
Dim subSubKey As String * MAX_TEXT_BUFF ' options subkey
Dim className As String * MAX_TEXT_BUFF
Dim keyLastWritten As FILETIME
' RegOpenKeyEx temps
Dim tempSubKey$
Dim tempAnotherSubKey$
' RegQueryValueEx temps
Dim strDataBuff As String * MAX_TEXT_BUFF
Dim strDataBuffSub As String
Dim lDataBuffSize As Long
' Cờ định hướng Export/Import
' True=Export, False=Import
Dim bExportImport As Boolean
Dim strTemp As String
' khởi tạo về vị trí
i% = 0
If ((strConverterDir = strREG_TEXT_CNV_IMPORT) Or _
(strConverterDir = strREG_GRAPH_FLT_IMPORT)) Then
bExportImport = False
Else
bExportImport = True
End If
' Mở đoạn Converters\Import key
res& = RegOpenKeyEx(lPredefRegKey, strConverterDir, _
0, KEY_ALL_ACCESS, keyHandleDummy)
If res& <> ERROR_SUCCESS Then
ReportRegError res&
Exit Sub
End If
' Đếm liệt kê tất cả converters và tốt nhất là mở các khoá keys
' cho mỗi converter subkey
Do While RegEnumKeyEx(keyHandleDummy, i%, subKey, MAX_TEXT_BUFF, 0, _
className, MAX_TEXT_BUFF, keyLastWritten) = ERROR_SUCCESS
' Mở nó
res& = RegOpenKeyEx(keyHandleDummy, subKey, 0&, KEY_ALL_ACCESS, _
subKeyHandle&)
' Nếu hỏng RegOpenKey thử lại 1 lần
If res& <> ERROR_SUCCESS Then
ReportRegError res&
Exit Do
Else
' Mở nội dung converter entries với khoá con Options subkey
res& = RegOpenKeyEx(subKeyHandle&, strREG_CNV_OPTIONS, 0&, _
KEY_ALL_ACCESS, subSubKeyHandle&)
lDataBuffSize = MAX_TEXT_BUFF
If res& = ERROR_SUCCESS Then
' thêm từng tên converter vào combo box
res& = RegQueryValueEx(subKeyHandle&, strWhatImLookingFor, _
0&, 0&, strDataBuff, lDataBuffSize)
If res& = ERROR_SUCCESS Then
' Ngắt trim và sửa cỡ của chuỗi string
strDataBuffSub = Left$(strDataBuff, lDataBuffSize - 1)
' và bảng table
clsCnvTable.AddConverter strDataBuffSub, subSubKeyHandle&, bExportImport
Else
'Thông báo lỗi ReportRegError res&
' converter kế tiếp với khoá Options key
GoTo ResumeDoLoop
End If
Else
GoTo ResumeDoLoop
End If
End If
ResumeDoLoop:
' make sure everything's neat and tidy
Call RegCloseKey(subKeyHandle&)
i% = i% + 1 ' i%++
Loop
' Rõ ràng và ngăn nắp...
Call RegCloseKey(keyHandleDummy)
Exit Sub
FatalError:
' Dọn dẹp xếp đặt
Set clsCnvTable = Nothing
DisplayErrorMsg strERR_INIT_MESSED_UP
End Sub
'------------------------------------------
' Thiết đặt radio buttons tuỳ theo
' thiết đặt trong list box
'------------------------------------------
Private Sub SetRadioButtons(ByVal strDummy As String)
' Các đối số có thể là "Yes" hoặc "No"
If strDummy = strOPT_YES Or strDummy = strOPT_NO Then
' Bật radio button bên phải lên
If strDummy = strOPT_YES Then
optYes.Value = True
optNo.Value = False
Else
optYes.Value = False
optNo.Value = True
End If
Else
DisplayErrorMsg strERR_WRONG_STRING
End If
End Sub
'-------------------------------------
' Cập nhật nội dung trong list box
'-------------------------------------
Private Sub UpdateOptions()
Dim i As Integer
Dim strListBoxEntry As String
' Các biến RegEnumValue
Dim hOptKey As Long ' Khoá Options reg key
Dim strValue As String * MAX_TEXT_BUFF
Dim lValueSize As Long
Dim dwTypeCode As Long
Dim strValueData As String * MAX_TEXT_BUFF
Dim lValueDataSize As Long
' Đầu tiên nhận và bỏ nội dung tồn tại
' (Nếu có bất cứ thứ gì trong List box)
If lstOptions.ListCount <> 0 Then
lstOptions.Clear
End If
' nhận key handle từ bảng table
hOptKey = clsCnvTable.OptionsHandle(cboConverters.SelText)
If hOptKey = 0 Then
GoTo FatalError
End If
' bây giờ nhận thiết đặt
dwTypeCode = 0&
lValueSize = MAX_TEXT_BUFF
lValueDataSize = MAX_TEXT_BUFF
' Thiết đặt gì?
i = 0
Do While RegEnumValue(hOptKey, i, strValue, lValueSize, 0&, dwTypeCode, _
strValueData, lValueDataSize) <> ERROR_NO_MORE_ITEMS
' Bỏ qua tất cả không phải chuỗi (non-string) các cặp Value=Data
If dwTypeCode <> REG_SZ Then GoTo ResumeDoLoop
' Đầu tiên ngắt và sửa các cỡ chuỗi
strListBoxEntry = Left$(strValue, lValueSize) & strEQUALS_SIGN & _
Left$(strValueData, lValueDataSize)
' lần lượt thêm vào list box
lstOptions.AddItem strListBoxEntry
lValueSize = MAX_TEXT_BUFF
lValueDataSize = MAX_TEXT_BUFF
ResumeDoLoop:
i = i + 1
Loop
If lstOptions.ListCount > 0 Then
lstOptions.ListIndex = 0
Else
GoTo FatalError
End If
Exit Sub
FatalError:
DisplayErrorMsg strERR_UPDATE_OPTIONS
End Sub
'--------------------------------------
' Chỉ thay đổi nội dung list box nếu
' lựa chọn mới khác
'--------------------------------------
Private Sub cboConverters_Change()
UpdateOptions
End Sub
Private Sub cmdHelp_Click()
MsgBox strHLP_DLG_MSG1 & Chr(10) & Chr(13) & _
strHLP_DLG_MSG2 & Chr(10) & Chr(13) & _
strHLP_DLG_MSG3, _
vbOKOnly, strHLP_DLG_CAPTION
End Sub
Private Sub cmdOK_Click()
' Xoá bảng table
Set clsCnvTable = Nothing
Unload formEdOptions
Exit Sub
End Sub
Private Sub cmdSet_Click()
CommitChange txtSetting.Value
End Sub
'----------------------------------------------------
' Đưa ra radio buttons hoặc thiết lập edit box
'----------------------------------------------------
Private Sub lstOptions_Change()
Dim strTemp As String
If lstOptions.Value <> "" Then
' khai triển chuỗi thực tế của option
strTemp = ExtractOptionData(lstOptions.Value)
'Nó là "Yes" hay "No"?
If strTemp = strOPT_YES Or strTemp = strOPT_NO Then
' Cho hiện các radio buttons, ẩn edit box
'đặt vào nút phải right button
SetRadioButtons strTemp
' Nếu edit box được hiện?
If txtSetting.Visible Then
' ẩn nó
lblSetting.Visible = False
txtSetting.Visible = False
cmdSet.Visible = False
' Hiện các nút!
optYes.Visible = True
optNo.Visible = True
End If
' Nó chỉ là một chuỗi string!
Else
' Cho hiện edit box, ẩn các radio buttons
' cập nhật các chuỗi thiết đặt
txtSetting.Value = strTemp
' các nút hiện?
If optYes.Visible Then
'ẩn chúng
optYes.Visible = False
optNo.Visible = False
' hiện edit box
lblSetting.Visible = True
txtSetting.Visible = True
cmdSet.Visible = True
End If
End If
End If
End Sub
Private Sub optNo_Click()
CommitChange strOPT_NO
End Sub
Private Sub optYes_Click()
CommitChange strOPT_YES
End Sub
' Khởi tạo dialog và control captions
Private Sub UserForm_Initialize()
' dialog caption
Caption = strMSG_CAPTION
' command buttons
cmdOK.Caption = strCMD_OK
cmdHelp.Caption = strCMD_HELP
cmdSet.Caption = strCMD_SET
' radio buttons
optYes.Caption = strOPT_YES
optNo.Caption = strOPT_NO
' nhãn labels
lblConversion.Caption = strLBL_CONVERSION
lblCnvOption.Caption = strLBL_CNV_OPTION
lblSetting.Caption = strLBL_SETTING
' lấp đầy combo box
If ControlsInit = False Then
fEditInitSuccess = False
DisplayErrorMsg strERR_NO_OPTIONS_FOUND
Else
fEditInitSuccess = True
End If
End Sub
2.2 Form thứ 2 có 1 nút lệnh
(Name)=RegOptionsForm
Caption=Thiết lập lựa chọn trong Registry'hay một tên khác tuỳ ý
(Name)=cmdClose
'Chèn 2 Page là
(Name)=Page1
(Name)=Page2
'Trang 1 có các control, bạn căn cứ vào tiếp đầu ngữ của tên để xác định, tôi bỏ giải thích vì quá dài
(Name)=lblWordOption
(Name)=lstWordOpt
(Name)=lblWordSetting
(Name)=txtWordSet
(Name)=lblWordOptDesc
'Trang 2
(Name)=lblEqOption
(Name)=lstEqOpt
(Name)=lblEqSetting
(Name)=txtEqSet
(Name)=lblEqOptDesc
'Viết lệnh cho form thứ 2
'Các biến lấy giá trị ra từ đường dẫn đờ phôn ngầm định của Word 2000 được viết bởi Word không viết nội dung của chúng vào Registry
Dim iAutoSavePath, iDocPath, iPictPath, iProgPath, iStartPath, iToolsPath, iUserPath, iWkgrpPath As String
Dim item__$(), List__$(), list2__$(), Key$, errortext$, sSection()
Dim WItem__$(), EQItem__$(), EQlist__$(), WList__$(), Wkey$, EQKey$, help$, RegOptions$, notset$, errmsg1$, change, errchange$
Dim Space_$, sWordSet, sEqSet
Dim LangList__$(), Lang__$(), CurLang$, NumLanguages, sLangLbl, sDictLbl, sEngLbl, sCancelMessage, sCancelTitle, sRegWord, sRegOpts, sRegProof, sRegEqDir, sRegEqGen
'========================
' Sub để định vị
'========================
Private Sub Localize()
Dim HelpTitle$
errortext$ = "Một lỗi sảy ra khi viết vào CSDL registration. Có lẽ lý do của trường hợp này là ảnh hưởng của thuộc tính READ ONLY trong thư mục Windows, hoặc Windows đang chạy ở chế độ Safe mode. Khởi động lại Restart Windows trước khi chạy lại Macro này."
CurLang$ = "1033" ' sử dụng ngôn ngữ đầu tiên trong danh sách
Space_$ = " "
sCancelMessage = "Bạn đã chọn cancel. Tất cả các thay đổi sẽ bị mất. Bạn có muốn tiếp tục và không cất những thay đổi mà bạn thiết lập không? Chọn No để cất những thay đổi."
sCancelTitle = "Thôi không lựa chọn Registry Options"
sSection(0) = "Word 2000 Options"
sSection(1) = "Equation Editor Options"
'-------Nhận các đường dẫn nội bộ đờ phôn Built-in Default mà không viết vào Registry-----
iAutoSavePath = Application.Options.DefaultFilePath(wdAutoRecoverPath)
iPictPath = Application.Options.DefaultFilePath(wdPicturesPath)
iProgPath = Application.Options.DefaultFilePath(wdProgramPath)
iStartPath = Application.Options.DefaultFilePath(wdStartupPath)
iToolsPath = Application.Options.DefaultFilePath(wdToolsPath)
iUserPath = Application.Options.DefaultFilePath(wdUserTemplatesPath)
iWkgrpPath = Application.Options.DefaultFilePath(wdWorkgroupTemplatesPath)
iDocPath = System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Options", "doc-path")
If iDocPath = "" Then
iDocPath = System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders", "Personal")
End If
No comments:
Post a Comment