显示标签为“软件编程”的博文。显示所有博文
显示标签为“软件编程”的博文。显示所有博文

2014年10月13日星期一

防止文件被改写的简单实现方式

最近在写的一个小程序中有个配置文件,这个文件对整个程序来说是至关重要的,如果它被删除或者改写的话,整个程序无法运行,或者运行后无法关闭。所以我一直在寻找如果让手工无法改写文件的方法。

对于“删除”来说是很容易解决的,程序中查找配置文件的路径,若为空则创建,并给些默认值。VB的示例代码如下:

FileName = App.Path + "\CONFIG"
'如果文件不存在,则创建文件
If Dir(FileName) = "" Then
Open FileName For Output As #1 '打开顺序文件,我们可以使用Open语句
a = Encode("123") + vbCrLf + "10" + vbCrLf 'vbCrLf为回车
Print #1, a '写数据
Close #1 '关闭文件
End If


对于手工改写配置文件,我一直无能为力,我试图在程序中把该文件隐藏掉。VB的示例代码如下:


SetAttr FileName, vbSystem Or vbHidden '隐藏文件


但终归来说是治标不治本,文件仍然会被改写的。然后我想到修改配置文件后缀法,让人手工没那么容易打开文件,但是总是有方法打开的。最终让我想到一个简单的解决方法是,在程序中先打开配置文件,之后手工就无法打开了。VB的示例代码如下:


Open FileName For Binary As #99

只是记得程序在改写该文件时要先关闭打开的文件,不然改写会失败的。VB的示例代码如下:


Close #99 '关闭文件

总结一下,防止文件被改写的简单实现方式就是在程序中先打开该文件。完整的程序示例可参考这里

2014年10月12日星期日

屏幕锁PcLocker更新

最近把以前写的一个小程序PClock做了一次更新,以前的程序是程序运行后系统界面锁定,需输入密码方能解锁。这次更新后的效果是,程序运行以后在后台监视空闲的时间(键盘和鼠标无动作),当空闲的时间等于设定时间时Windows系统界面锁定。

就是这么一个小功能的更新,花了我3天的时间,主要原因是走了不少的弯路。在差不多要放弃的时候让我找到了解决的方法

程序的界面和功能没有太大的改变,以下是程序的ChangeLog:

1、程序的名称从PClock改为PcLocker

2、程序转为后台运行,当系统空闲时锁定Windows系统,类似于进入屏幕保护程序

3、改变了禁用任务管理器的方式

4、实现了手工无法修改配置文件

5、优化并精简了代码

6、程序适用于Windows XP、Windows 7,其他的系统没有测试

7、初始密码123,程序默认空闲启动时间为10分钟,默认随机自启动关闭

源程序的下载地址:点我

下面就是整个程序的源码,主要包括1个模块module1.bas,1个主程序窗口MainForm.frm,1个设置窗口setform.frm

主程序窗口MainForm.frm的代码如下,程序的主要功能集中在此。

'计算空闲时间
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function EnableWindow Lib "user32" (ByVal hWnd As Integer, ByVal aBOOL As Integer) As Integer
Private Declare Function IsWindowEnabled Lib "user32" (ByVal hWnd As Integer) As Integer
Private Declare Function GetMenu Lib "user32" (ByVal hWnd As Integer) As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByVal lpvParam As Any, ByVal fuWinIni As Long) As Long

'常量声明
Const SWP_NOMOVE = &H2 '保持当前位置(x和y设定将被忽略)
Const SWP_NOSIZE = &H1 '保持当前大小(cx和cy会被忽略)
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2
Const flags = SWP_NOMOVE Or SWP_NOSIZE

'使用GetLastInputInfo来检测键盘、鼠标无动作
Private Declare Function GetLastInputInfo Lib "user32" (plii As LASTINPUTINFO) As Boolean
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type

Private Sub Form_Load()
If App.PrevInstance = True Then
'用APP对象的PrevInstance属性,防止同时运行屏幕保护程序的两个实例
Unload Me
Exit Sub
End If

Timer1.Interval = 1000
'读取配置信息
Call GetConfig
'打开配置文件,防止手工修改
FileName = App.Path + "\CONFIG"
Open FileName For Binary As #99
End Sub

Private Sub BntOk_Click()
If (Text1.Text = password) Then
' 卸载钩子
UnhookWindowsHookEx lHook

Timer1.Enabled = True
Me.Visible = False
Text1.Text = ""
Timer2.Enabled = False
Else
Label2.Visible = True
Label2.Caption = "输入密码不正确,请重新输入!"
Text1.Text = ""
Text1.SetFocus
End If
End Sub

Private Sub BntEmpty_Click()
Text1.Text = ""
End Sub

'显示主程序界面
Private Sub ShowForm()
' 安装钩子
lHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf CallKeyHookProc, App.hInstance, 0)

'如果更改的背景文件不存在,或者文件目录为空,则显示默认背景
If (filedir <> "" And Dir(filedir) <> "") Then
'开始的时候使用的是改变窗口的默认背景,这样的话这个背景不会被拉伸,只能保持默认大小,舍弃 Me.Picture = LoadPicture(filedir)
'现在使用image控件来实现
Image1.Width = Screen.Width
Image1.Height = Screen.Height

'这里把窗口设为全屏,因为image 要随着窗口变化
Top = 0
Left = 0
Me.Width = Screen.Width
Me.Height = Screen.Height

Me.Image1.Visible = False
Me.Image1.Picture = LoadPicture(filedir)
Me.AutoRedraw = True
Me.PaintPicture Image1.Picture, 0, 0, Me.ScaleWidth, Me.ScaleHeight
End If

Me.Show 'setFocus前面须有这个
'设置窗口在最上面
Dim Ok
Ok = SetWindowPos(Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, flags)
'设置全屏
Top = 0
Left = 0
Me.Width = Screen.Width
Me.Height = Screen.Height
'设置输入框的位置
Frame1.Top = Screen.Height - Frame1.Height
Frame1.Left = Screen.Width - Frame1.Width
Label2.Left = Frame1.Left
Label2.Top = Frame1.Top - Label2.Height
Label2.Width = Frame1.Width
Label2.Visible = False
Text1.SetFocus
'禁用alt+ctrl+delete
'Open Environ$("WinDir") & "\system32\taskmgr.exe" For Binary As #1
Timer1.Enabled = False
Timer2.Enabled = True
Text1.SetFocus
End Sub
'设置窗口
Private Sub BntSet_Click()
If (Text1.Text = password) Then
' 卸载钩子
UnhookWindowsHookEx lHook
Me.Visible = False
Text1.Text = ""
setform.Show
Timer1.Enabled = True
Else
Label2.Visible = True
Label2.Caption = "输入密码不正确,请重新输入!"
Text1.Text = ""
Text1.SetFocus
End If
End Sub

'回车之后的动作
Private Sub Text1_KeyPress(KeyAscii As Integer)
' Text1 响应回车键
If KeyAscii = 13 Then
If (Text1.Text = password) Then
' 卸载钩子
UnhookWindowsHookEx lHook
Me.Visible = False
Text1.Text = ""
Timer1.Enabled = True
Timer2.Enabled = False
Else
Label2.Visible = True
Label2.Caption = "输入密码不正确,请重新输入!"
Text1.Text = ""
Text1.SetFocus
End If
End If
End Sub
'当空闲时间大于IntervalTime时,调用ShowForm
Private Sub Timer1_Timer()
Dim lii As LASTINPUTINFO
lii.cbSize = Len(lii)
If GetLastInputInfo(lii) Then
If (GetTickCount - lii.dwTime)/60000 > IntervalTime Then
Call ShowForm
End If
End If
End Sub
'禁用任务管理器
Private Sub Timer2_Timer()
Shell ("cmd /c taskkill /f /im taskmgr.exe"), vbHide
End Sub

设置窗口setform.frm的代码,包括密码设置、背景图片设置、开机自启动设置和空闲启动时间设置。

Dim change As Boolean
Private Sub Command1_Click()

'先读出密码
passwordstr = password
FileName = App.Path + "\CONFIG" '配置文件路径
'验证密码
If Text1.Text = passwordstr And Text3.Text = Text2.Text Then
NewPassword = Encode(Text2.Text)
change = SetConfig(NewPassword, 0)
'设置以后重新读取配置文件
Call GetConfig
If (change = True) Then MsgBox "口令修改成功"
Else
If Text2.Text <> Text3.Text Then
MsgBox "两次口令输入不一致,请重新输入"
Else
MsgBox "旧口令错,请重新输入"
End If
End If
End Sub

Private Sub Command2_Click()
Unload Me
End Sub


Private Sub Command3_Click()
Set w = CreateObject("wscript.shell")
w.regwrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\" & App.EXEName, App.Path & "\" & App.EXEName & ".exe"
MsgBox "已经设置为开机自启动"
End Sub

Private Sub Command4_Click()
Set w = CreateObject("wscript.shell")
w.regdelete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\" & App.EXEName
MsgBox "已经取消开机自启动"
End Sub

Private Sub Command5_Click()

CommonDialog1.Filter = "jpg|*.jpg"
CommonDialog1.ShowOpen
filedir = CommonDialog1.FileName
If (filedir <> "") Then change = True

change = SetConfig(filedir, 2)
'设置以后重新读取配置文件
Call GetConfig
If (change = True) Then MsgBox "背景替换成功"
End Sub

Private Sub Command6_Click()
change = SetConfig("", 2)
'设置以后重新读取配置文件
Call GetConfig
If (change = True) Then MsgBox "已恢复为默认背景"
End Sub

Private Sub Command7_Click()
Unload Me
End Sub

Private Sub IntervalBnt_Click()
change = SetConfig(setform.IntervalTxt.Text, 1)
'设置以后重新读取配置文件
Call GetConfig
If (change = True) Then MsgBox "修改成功"
End Sub

模块module1.bas代码,主要是禁用键盘和加密函数。

Option Explicit

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Const HC_ACTION = 0
Public Const WM_KEYDOWN = &H100
Public Const WM_KEYUP = &H101
Public Const WM_SYSKEYDOWN = &H104
Public Const WM_SYSKEYUP = &H105
Public Const VK_TAB = &H9
Public Const VK_CONTROL = &H11
Public Const VK_ESCAPE = &H1B
Public Const VK_DELETE = &H2E
Public Const WH_KEYBOARD_LL = 13
Public Const LLKHF_ALTDOWN = &H20

'禁用键盘的功能键
Public Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
flags As Long
time As Long
dwExtraInfo As Long
End Type
Public lHook As Long
Dim p As KBDLLHOOKSTRUCT
Dim key() As Byte
'全局变量
Public password As String
Public IntervalTime As Integer
Public filedir As String
Public FileName As String

'键盘钩子
Public Function CallKeyHookProc(ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim fEatKeystroke As Boolean

If (ncode = HC_ACTION) Then
If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Or wParam = WM_KEYUP Or wParam = WM_SYSKEYUP Then
CopyMemory p, ByVal lParam, Len(p)
fEatKeystroke = _
((p.vkCode = VK_TAB) And ((p.flags And LLKHF_ALTDOWN) <> 0)) Or _
((p.vkCode = VK_ESCAPE) And ((p.flags And LLKHF_ALTDOWN) <> 0)) Or _
((p.flags And LLKHF_ALTDOWN) <> 0) Or _
((p.vkCode = VK_ESCAPE) And ((GetKeyState(VK_CONTROL) And &H8000) <> 0)) Or _
((p.vkCode = 91) Or (p.vkCode = VK_ESCAPE) Or (p.vkCode = 92) Or (p.vkCode = 93))
'判断是否按下了:TAB+ALT、Esc+ALT、Alt(Alt+F4)、Esc+Ctrl、左右 Win 和徽标键\Esc
End If
End If

If fEatKeystroke Then
' 设置为 1 可以屏蔽按键
CallKeyHookProc = 1
Else
CallKeyHookProc = CallNextHookEx(0, ncode, wParam, ByVal lParam)
End If
End Function

Sub initkey() '这里为密匙,建议定义的复杂些,我这里仅仅是个示例
ReDim key(9)
key(0) = 12
key(1) = 43
key(2) = 53
key(3) = 67
key(4) = 78
key(5) = 82
key(6) = 91
key(7) = 245
key(8) = 218
key(9) = 190
End Sub

Function Encode(ByVal s As String) As String '加密
On Error GoTo myerr
initkey
Dim buff() As Byte
buff = StrConv(s, vbFromUnicode)
Dim i As Long, j As Long
Dim k As Long
k = UBound(key) + 1
For i = 0 To UBound(buff)
j = i Mod k
buff(i) = buff(i) Xor key(j)
Next
Dim mstr As String
mstr = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim outstr As String
Dim temps As String
For i = 0 To UBound(buff)
k = buff(i) \ Len(mstr)
j = buff(i) Mod Len(mstr)
temps = Mid(mstr, j + 1, 1) + Mid(mstr, k + 1, 1)
outstr = outstr + temps
Next
Encode = outstr
Exit Function
myerr:
Encode = ""
End Function
Function Decode(ByVal s As String) As String '解密
On Error GoTo myerr
initkey
Dim i As Long, j As Long
Dim k As Long, n As Long
Dim mstr As String
mstr = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim outstr As String
Dim temps As String
If Len(s) Mod 2 = 1 Then
Decode = ""
Exit Function
End If
Dim t1 As String
Dim t2 As String
Dim buff() As Byte
Dim m As Long
m = 0
For i = 1 To Len(s) Step 2
t1 = Mid(s, i, 1)
t2 = Mid(s, i + 1, 1)
j = InStr(1, mstr, t1)
k = InStr(1, mstr, t2)
n = j - 1 + (k - 1) * Len(mstr)
ReDim Preserve buff(m)
buff(m) = n
m = m + 1
Next
k = UBound(key) + 1
For i = 0 To UBound(buff)
j = i Mod k
buff(i) = buff(i) Xor key(j)
Next
Decode = StrConv(buff, vbUnicode)
Exit Function
myerr:
Decode = ""
End Function

'配置信息
'定义变量,password密码,IntervalTime空闲时间


Function GetConfig()
Dim s As String, t() As String, a As String
FileName = App.Path + "\CONFIG"
'如果文件不存在,则创建文件
If Dir(FileName) = "" Then
Open FileName For Output As #1 '打开顺序文件,我们可以使用Open语句
a = Encode("123") + vbCrLf + "10" + vbCrLf 'vbCrLf为回车
Print #1, a '写数据
Close #1 '关闭文件
'隐藏文件
'SetAttr FileName, vbSystem Or vbHidden
End If
Open FileName For Binary As #11
s = Input(LOF(11), #11)
Close #11
t = Split(s, vbCrLf)
password = Decode(t(0))
IntervalTime = t(1) '第三行是2,第四行是3,类推
filedir = t(2)
End Function

Function SetConfig(ByVal Value As String, ByVal Weizhi As Integer) As Boolean
Close #99 '关闭打开的配置文件
FileName = App.Path + "\CONFIG"
Dim s As String, t() As String
Open FileName For Binary As #123
s = Input(LOF(123), #123)
Close #123
t = Split(s, vbCrLf)
t(Weizhi) = Value '第三行是2,第四行是3,类推
s = Join(t, vbCrLf)
Kill FileName
Open FileName For Binary As #11
Put #11, , s
Close #11
SetConfig = True
Open FileName For Binary As #99 '打开配置文件,防止手工修改
End Function

2014年10月11日星期六

VB禁用Ctrl-Alt-Delete/任务管理器的方法

在Windows XP下禁用Ctrl-Alt-Delete的方法比较简单,因为Ctrl-Alt-Delete组合键的功能就是调用任务管理器,直接把任务管理器给禁用了,Ctrl-Alt-Delete的功能也就没有了,相当于也给禁用了。这个方法的简单的实现是用二进制 stream 形式先打开 C:\windows\system32\taskmgr.exe任务管理器程序,使后续无法手工正常打开任务管理器。代码如下:

Open "C:\WINDOWS\system32\taskmgr.exe" For Binary As #1

这种方法在XP上是可行的,但是在VISTA和WIN7上是无效的。我的解决方法是用taskkill命令来结束任务管理器程序taskmgr.exe。代码如下:

Shell ("cmd /c taskkill /f /im taskmgr.exe"), vbHide

在VB程序里实现的话,最好把上述语句放到Timer事件中,每隔一段时间执行一次,就能实现禁用任务管理器的目的了。代码如下:

Private Sub Timer1_timer()
Shell ("cmd /c taskkill /f /im taskmgr.exe"), vbHide
End Sub

2014年10月10日星期五

VB键盘鼠标无动作调用程序的尝试

我想要实现的功能是,当键盘无输入、鼠标无移动或点击动作时调用程序。首先想到的是用钩子HOOK来获取键盘或者鼠标的动作,如果无动作时调用程序。我尝试的结果是HOOK来HOOK去总是有问题。

后来想到Windows的屏幕保护程序就是当键盘鼠标无动作时进入屏幕保护的,于是改变思路,想把程序做成这样的形式,键盘鼠标无动作,系统进入屏幕保护,然后检测系统是否运行屏幕保护程序,如果运行的话则调用程序。这种方式就是以屏幕保护程序作为中介,把检测键盘鼠标动作的工作交给屏幕保护程序来完成了。SystemParametersInfo可以实现获取屏幕保护信息的函数。参考代码如下:

'API调用与常用定义:
Private Declare Function SystemParametersInfo _
Lib "user32" _
Alias "SystemParametersInfoA" _
(ByVal uiAction As Long, _
ByVal uiParam As Long, _
pvParam As Any, _
ByVal fWInIni As Long) As Boolean

Private Const SPI_GETSCREENSAVEACTIVE As Long = &H10 '屏保是否启用的常量
Private Const SPI_GETSCREENSAVERRUNNING As Long = &H72 '屏保是否运行的常量

Private Sub Timer1_Timer()
Dim bRunning As Boolean '屏保是否运行的变量,当然你可以定义全局变量
SystemParametersInfo SPI_GETSCREENSAVERRUNNING, 0, bRunning, False '调用API,bRunning返回屏保运行状态
Debug.Print Time; "屏保运行="; bRunning '演示:打印屏保是否运行的信息
End Sub

'另外,查看屏保是否启用,也可以用下面方法:
SystemParametersInfo SPI_GETSCREENSAVEACTIVE, 0, bActive, False 'bActive为返回值(逻辑型)


可是不知道为什么我在WIN7下调试还是有问题,提示SystemParametersInfo SPI_GETSCREENSAVERRUNNING, 0, bRunning, False
中的bRunning类型错误,只能作罢。

最后来说一下最终实现的方案是使用GetLastInputInfo函数获取系统的空闲时间,参考代码如下:

Option Explicit
Private Declare Function GetLastInputInfo Lib "user32" (plii As LASTINPUTINFO) As Boolean
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type

Private Sub Form_Load()
Timer1.Interval = 1000
End Sub

Private Sub Timer1_Timer()
Dim lii As LASTINPUTINFO
lii.cbSize = Len(lii)
If GetLastInputInfo(lii) Then
If (GetTickCount - lii.dwTime) / 60000 >= 15 Then
Call MsgBox("由于本机15分钟没有操作,如果3分钟后没有反应,系统将强制关机", vbYesNo + vbExclamation + vbDefaultButton2, "提示")
End If
End If
End Sub

2014年9月28日星期日

用网线来实现2台电脑之间拷贝文件

我需要把一台电脑上的几十G的大文件拷贝到另一台电脑上,首先想到的是使用移动硬盘,可是我手头上只有16G的U盘。于是我想到的是A电脑的文件拷贝到U盘,然后U盘再拷贝到B电脑,之后重复上述的操作。

可是USB2.0读写速度太慢了,几十G的东西要花费1个多小时,之后再拷贝到另一台电脑上还要花费等长的时间。这时突然想到上学时用1根网线做成交叉线连接2台电脑的事情。于是找来1条网线,把2台电脑的网段都设成192.168的网段,互相都能PING通,说明2台电脑连接成功了。然后再设置网上邻居和共享文件夹,完成之后就能拷贝文件了。

2台电脑直接连接拷贝东西比用移动硬盘等介质方便省时得多,虽然前期配置稍微花费点时间,之后差不多能省下一半的时间了。

2014年8月6日星期三

ACCESS使用VBA实现列值累加并取得累加阀值的记录

题目很拗口,主要是想要表达的东西比较曲折,还是以实例来说明比较直观,假设在Access中有以下的表table1。table1是一张成绩表,我想要的结果是:所有人的成绩按着总分(Score)从大到小排列,然后在排列好的表中从上到下累加English/Score列(第1行+第2行+……+第N行的值),当累加值>0.7时,取出第1行到第N行的记录。

2014年6月22日星期日

笔记本硬盘故障

前一段一个周末的某一天,我像往常一样玩过电脑准备关机,电脑卡得不行,根本没法操作,我被迫用“任务管理器”里的“关机”来关机。

等吃过中午饭,Jasmine提醒我说,为什么电脑的电源键还在亮着。

我检查发现电源灯确实在亮着,把笔记本翻过来,扣掉电池,灯灭了。

第二天开电脑,进不了系统,黑底白字提示“A disk read error occurred,Press Ctrl + Alt + Del to restart”,在我反复按Ctrl + Alt + Del重启机器几十次之后,依然进不了系统。

Dell自带的有一个检测工具,我测的结果显示“Error code 2000-0146”,跳过之后还有一大堆类似的代码出现。不明所以,上网查找原因,有人说是硬盘故障。

第三天把电脑拿到朋友那里去检修,他检查发现我的电脑系统盘没有内容,我和他都很纳闷。我让他给我重装了系统,装系统的过程很缓慢,他说可能硬盘有问题。

好不容易装好了系统,我赶紧借了个移动硬盘把电脑上的资料全部拷出来。

刚拷出来电脑就卡死了,再次开机,系统提示缺少系统文件。

再到朋友那里,他用磁盘检查工具检查了我的硬盘,发现有好多坏道。我问他能不能重新分区,把坏道隐藏掉。他说,如果坏道集中的话没有问题,如果坏道散乱的话就很困难了。

我的磁盘属于后者,检测的过程中过一段就会出现严重的坏道,这样的结果是要换硬盘了。

从网上买了个硬盘装上,电脑死而复生。我赶紧把重要的资料刻录成盘以备不测,都说“数据无价”,如果磁盘坏到起不来了,那就更可怕了。这次还好,没有坏的那么彻底,不然会哭死不可,电脑上有好多熊仔的相片在里面。

上次有个朋友的硬盘坏了,根本没法运转,想把里面的数据拷出来都不行。她急切地找到专业的数据恢复机构,花了几千块,开了硬盘才拿出数据。我问她,电脑上的东西有那么重要,非要花那么多钱找回来?她说,照了好多照片,很重要的。那时我不懂,现在我知道有些照片是唯一的,丢了就再也找不回来了。

电脑买了5年了一直都没有问题,突然就坏的很严重。网上说,硬盘从3年以后故障率上升,5年后到了高危期。以前想着云端的数据不安全,总是把资料在本地备份一个,没想到本地的硬盘也会坏掉,以后要做好重要数据备份容灾了。我想最简单有效并廉价的方法就是刻盘了,一张DVD光盘可以装4.7G的东西才块把钱。如果你的硬盘使用超过了5年的话,赶紧行动吧!

PS:笔记本装过系统后开机发现屏幕很模糊,字体看不清楚,我把分辨率调到最大了还是不行。网上说可能是驱动的问题,我下载了驱动精灵,更新了驱动程序,问题得以解决。

UltraWebGrid导出Excel的方法

这段时间需要用C#做个页面,把网格中查询出来的数据导出到Excel中。在网上找了一大堆C#导出Excel的代码,试来试去都不可用。好多代码是针对.net 2.0或者3.0的,无奈我的程序用的是.net 1.0开发的,造成好多函数都不能用。之后就转变思想,寻找“UltraWebGrid导出Excel的方法”,在CSDN中找到一批流传甚广的文本,可是我人肉测试的结果还是不能用。就在我近乎绝望的时候,我发现原来UltraWebGrid自带导出Excel的控件。使用也很简单,前端注册,后台调用就行了。以下是一个简单的实例。

PS:UltraWebGrid的中文文档真的太少了,使用起来很不方便。

modle.aspx的代码如下,第1行注册控件,第2行添加一个导出按钮,第3行添加UltraWebGridExcelExporter控件。


<%@ Register Assembly="Infragistics.WebUI.UltraWebGrid.ExcelExport.v5.1, Version=5.1.20051.37, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" Namespace="Infragistics.WebUI.UltraWebGrid.ExcelExport" TagPrefix="igxl" %>




modle.aspx.cs代码如下,定义UltraWebGridExcelExporter,然后调用Export函数。



protected Infragistics.WebUI.UltraWebGrid.ExcelExport.UltraWebGridExcelExporter UltraWebGridExcelExporter1;
private void Button2_Click(object sender, System.EventArgs e){
UltraWebGridExcelExporter1.Export(this.UltraWebGrid1);
}

2014年5月14日星期三

C#将文件复制到指定文件夹,并按日期归档

下面是在C#中将文件复制(剪切是先复制再删除)到指定的路径,并按日期归档的一个简单实例。值得注意的2点是:

1)文件的路径是关键,程序中使用双斜杠\\

2)文件和文件夹的区别


private void DoWork()
{
String dir="D:\\ABC"
//创建备份文件夹,按时间命名
String bakDir = dir + "\\bak\\" + DateTime.Now.ToString("yyyy-MM-dd");

if (Directory.Exists(bakDir) == false){
Directory.CreateDirectory(bakDir);
}
string[] files = Directory.GetFiles(dir);
if (files.Length != 0) {
foreach (string file in files) {
FileInfo fileinfo = new FileInfo(file);
try{
string fileName = file.Replace(dir, "");
//备份文件
File.Copy(file,Path.Combine(bakDir,fileName));
File.Delete(file);
}
}
}

2014年4月30日星期三

感受Symbian V5

用了诺基亚5233一个月多了,下面来说一说使用的感受。

从安卓过来,使用中心里会不自觉地对比这两个系统的差别。

先说优点,没想到Symbian s60上有这么多流行的应用可用,比如Gmail、微信、QQ、百度输入法WordPress、百阅、来电通等,所以刚开始让我兴奋了一把,以为塞班与安卓不会差太远。可是我错了。使用塞班的过程中你总会体会到这样或那样的不爽。

它的PC套件安装繁琐,使用也极不方便,更要命的是应用市场的应用很难安装到手机里,总是一个劲儿地提示“连接不上”。

电阻屏的灵敏度太低,按起来太费劲了,有些时候按下去了根本没反应,打字的时候更要命,少个字母整句话都要删除重来。更傻逼的是,塞班的菜单项目每次都要按两次才能进去,一次选中,一次打开。

塞班系统没有菜单键和返回键,这两个键的使用频率很高,这就使得每个应用都必须做一个虚拟的菜单功能和返回功能按钮。也就是这个差别,从安卓过来使用同样的应用体验很不一样。

塞班输入框傻傻地是固定位置,很容易被输入法界面遮挡,编辑文字很不方便。

塞班系统自定义性不强,操作繁琐,应用程序少的可怜,趣味性不够,简洁性也不好,使用起来很不方便,有时候真怀疑它不是一步智能机。诺基亚真是可惜了,尾大不掉,如果当初在走下坡路前选择安卓的话,不知道会不会是另一番景象。信息产业真的是变幻莫测,此时的如日中天,转瞬间就烟消云散。看看摩托罗拉,再看看雅虎,真是让人唏嘘不已。

2014年4月2日星期三

狗屎的Gtalk,狗屁的环聊

这几天手机怀了,用起了妹妹遗弃很久的诺基亚5233.很久没用诺基亚的手机了,从安卓转过来有点不习惯,不过5233怎么说也是个智能手机了,多少也有个智能机的样子。

拿到手机后,第一件事就是折腾通讯录。以前的手机通讯录都是同步到Google的,这下不能通过Google同步到诺基亚了。只能采取笨方法,导出到SD卡,然后从SD卡导入。谁知道,安卓导出到SD卡的是一个CSV文件,不是一个个的CSV文件,导致导入诺基亚以后只能导入一条记录。万事问谷歌,上网搜索“安卓通讯录导入诺基亚”,返回的结果都是“诺基亚通讯录导入安卓”,看来诺基亚真的是昨日黄花了。有人教授借助OUTLOOK等方法。之后让我找到了一个简单的方法,用“QQ同步助手”。两个手机同时安装该软件,用QQ登录,上传下载即可。看来关键时刻还是用国货啊。

我渐渐发现国货的好来,像腾讯、百度跨平台的软件做得很好,使用起来几乎没有隔阂感。手机迅速安装了QQ、微信、百度输入法。而谷歌在诺基亚S60上几乎没什么应用可用。我唯一牵挂的是Gtalk,用了好多年了,上面的联系人只有几个人,联系最多的还是Jasmine。当时看重Gtalk的原因是它轻巧,保存聊天记录到Gmail。到现在我和Jasmine聊天也都用Gtalk,我们不需要花哨的功能(虽然它功能简单到令人发指,而且好多年没有更新)。

诺基亚上没有谷歌官方出品的Gtalk,找了好多天也没有找到适合的替代品,用了Talknaut、Nimbuzz都不满意,连接时间太久,网络延迟太严重。现在手机上只能放弃Gtalk了。在找Gtalk的时候让我知道了“环聊”,虽然Gmail一直有提示,都没太注意。原来谷歌直接把Gtalk搞死,搞出环聊,替代Gtalk,增加了我不需要的视频、打电话的功能。最搞笑的是Windows不提供客户端软件,只能用Chrome的插件才能用。而且这个插件做得真够烂的,关键是不提供“在线状态”的功能了,看不到联系人是否在线,和微信一样。使用的体验跟国产的QQ真的是没法比。

这几年越来越看不懂Google了,Reader死了,Gtalk也死了,谷歌老矣?

2014年3月28日星期五

解决SQL Server 2008+ Reporting Services (SSRS)使用USER登录问题

我的数据库和报表服务的版本如下:

数据库:SQL Server 2008 R2
报表服务:SQL Server 2008 R2 Reporting Services

我本想让用户像访问网站一样访问我的报表服务,该死的SQL Server Reporting Services从2005以后就不依赖于IIS,造成用户不能匿名访问了。

网上有关于“SQL Server 2008 Reporting Services匿名访问”的教程,通过修改Reporting Services下的配置文件来实现,我对着着教程做了一遍,没有成功。

突然想到,我只是让有权限的USER账号能访问就行,没必要实现匿名访问。当别人用别的计算机访问该服务时总是提示“没有权限”,而把这个人的账号加入服务器的Administrators组里面时就能访问了,别的组却都不能访问。于是想到会不会是Reporting Services的配置项的访问权限只对Admin开放?之后证明我的推断是正确的,也让我找到了SSRS使用USER登录的方法,步骤如下:

1、用Administrator进入报表管理器URL:http://localhost/Reports
2、主文件夹的“安全性”,新建角色分配,把Users组加进去
3、进入右上角的“站点设置”,新建角色分配,把Users组加进去
4、进入“文件夹设置”,新建角色分配,把Users组加进去

也就是把Users组加入站点和文件夹的相应权限当中去。

总算解决了,差点就把数据库装回SQL Server 2000了。

参考:http://www.soheib.com/technical-knowledge/sql-server-2012-reporting-services-uac-user-access-control/

2014年3月27日星期四

编辑SWF的方法

最近几天帮人改网站,该网站的顶部位置放一个SWF做背景。首先我狠狠地把他给鄙视了一番,这都啥年代了还有人用Flash做顶部图片。本想把他的这个SWF换成JPEG的文件,可谁知这家伙把Top.swf放的到处都是,也懒得看他的代码,想直接把这个SWF给改一下。

首先下载安装Adobe Flash CS,装上了才发现它死活不给修改SWF的文件。在网上找“SWF编辑”的方法,让我找到了一款“SWF TO FLV”的软件Imperator FLA——它能把SWF转换成FLV。

下面的问题就很容易了,在Adobe Flash CS编辑转换的FLV即可,改完之后“发布预览”就保存成SWF的文件了。

2013年10月21日星期一

C#在App.config中自定义节点的设置与读取实例

我们往往需要在App.config中自定义一些节来满足实际需要,而不依赖于App.config的appSettings,下面通过一个简单的实例来说明自定义配置节点的设置与读取(该实例抽取于FTP上传程序)。

在App.config配置文件中使用自定义配置,需要在configSections中添加一个section元素,并指定此section元素对应的名字和类型,然后再在configuration根节点下面添加此自定义配置节。

1、我们在App.config中添加如下的自定义节点(配置了一组相同类型的节点,用于上传文件目录,FTP服务器地址及登陆信息):




D:\ABC\1\
D:\ABC\
ftp://10.1.1.2
user
1234


D:\ABC\2\
D:\ABC\
ftp://10.1.1.3
user
1234


D:\ABC\3\
D:\ABC\
ftp://10.1.1.4
user
1234



2、然后在App.config的configSections中添加section元素(section 元素将配置节处理程序与配置元素或节关联)(其中name为自定义节点的名称,type为自定义节点解析文件的命名空间和自定义节处理程序的类名)





3、创建自定义配置节处理程序,节处理程序用来解释并处理 Web.config 文件特定部分中 XML 配置元素中定义的设置,并根据配置设置返回适当的配置对象。使用该配置对象,以对自定义配置元素进行读取和写入。新建名为DZConfig.cs的文件,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Collections;


namespace FTP_SendServices
{
public class DZConfigSection
{
DZConfigSection() { }
#region 属性定义

private string _FilePath;
private string _LogPath;
private string _uploadUrl;
private string _userName;
private string _passWord;

public string FilePath
{
get { return _FilePath; }
set { _FilePath = value; }
}

public string LogPath
{
get { return _LogPath; }
set { _LogPath = value; }
}

public string uploadUrl
{
get { return _uploadUrl; }
set { _uploadUrl = value; }
}


public string userName
{
get { return _userName; }
set { _userName = value; }
}

public string passWord
{
get { return _passWord; }
set { _passWord = value; }
}



#endregion


public DZConfigSection(XmlNode AddressConfig)
{
XmlElement c = (XmlElement)AddressConfig;
_FilePath = c.SelectSingleNode("FilePath").InnerText;
_LogPath = c.SelectSingleNode("LogPath").InnerText;
_uploadUrl = c.SelectSingleNode("uploadUrl").InnerText;
_userName = c.SelectSingleNode("userName").InnerText;
_passWord = c.SelectSingleNode("passWord").InnerText;

}

}

//创建一个实现 System.Configuration.IConfigurationSectionHandler 接口的公共类。
public class ConvertCfgSectionHandler : IConfigurationSectionHandler
{
public ConvertCfgSectionHandler() { }
public object Create(object parent, object configContext, XmlNode section)
{
//添加您自己的代码,以执行所需的配置工作。
List _list = new List();
foreach (XmlNode AddressConfig in section.SelectNodes("//AddressConfig"))
{
DZConfigSection _DZConfig = new DZConfigSection(AddressConfig);
_list.Add(_DZConfig);
}
return _list;

}


}

public class DZConfig
{

public static List GetConfigList()
{

return (List)ConfigurationSettings.GetConfig("DZConfig");
}
}
}

4、在程序中使用配置节点信息。下面就是节点的读取,遍历整个自定义节点的数据:

List _ConfigList = DZConfig.GetConfigList();
foreach (DZConfigSection Config in _ConfigList)
{
LogPath =Config.LogPath + "log" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
FileHelper.WriteFile(LogPath, DateTime.Now.ToString() + "   数据发送功能启动!");
string dir = Config.FilePath;
string uploadUrl =Config.uploadUrl;
string userName = Config.userName;
string passWord = Config.passWord;
string[] files = Directory.GetFiles(dir);
}

2013年10月4日星期五

C#验证控件validator的简单实例

ASP.NET为开发人员提供了一套简单实用的服务器控件来验证用户输入的信息是否有效。这些控件的主要属性有id(控件的唯一id)、ControlToValidate(被验证的控件的id)、ErrorMessage(当验证失败时,在控件中显示的文本)、runat(规定该控件是一个服务器控件。必须设置为 "server")。

1、RequiredFieldValidator:验证一个必填字段,如果这个字段没填,那么将不能提交信息。

下例为文本框输入是否为空的验证,输入内容为空时报错。代码如下:


*


2、CompareValidator:比较验证。比较两个字段值是否相等,如密码和确认密码两个字段是否相等;比较一个字段与一个具体的值。

下例为两个文本框的输入密码验证,如果两个文本框输入内容不一致时报错。代码如下:






下例为文本框输入内容值验证,如果输入内容和某值相等时报错。代码如下:





3、RangeValidator:范围验证。验证一个字段是否在某个范围中。

下例为文本框输入的内容在最大值和最小值之间,如果超过最大或最小值时报错。代码如下:





4、RegularExpressionValidator:正则表达式验证。它根据正则表达式来验证用户输入字段的格式是否合法,如电子邮件、身份证、电话号码等。

下例为文本框输入内容符合ValidationExpression中正则表达式的要求,如果不符合要求时报错。代码如下:



2013年9月17日星期二

用Google通讯录在线编辑你的安卓手机通讯录

安卓手机用久了,通讯录必然会越来越长,越来越乱,所以偶尔要清理一下通讯录。当然你可以在手机上左划划右滑滑编辑你的通讯录,但是远没有在电脑上来的方便。

电脑上这类的软件多的哟数也数不清,比如某豆荚,某卫士,某Q。不过如果你不用这类软件也可以有个更简单的方法,上在线的谷歌通讯录,这可是官方的通讯录哦。但是前提是你的安卓手机要登录Google帐号,并同步联系人。也就是说你必须把手机上的通讯录同步到网上。

同步之后,登录谷歌通讯录,之后就可以编辑通讯录中的内容了。它包括新建、导入、导出、分组、合并、添加联系人图片等功能,也够强大了。

2013年7月19日星期五

我的安卓应用列表

安卓手机用了快两年了,下面罗列一下自己经常使用的Android APPS吧。

1、8684公交

俺现在没有小汽车,没有摩托车,没有电动车,也没有自行车,出门全靠公交车了,8684公交是一款不错的安卓应用,数据更新及时准确,哪条路在修路公交改道了它立马都能知道。

2、布丁优惠券

去吃麦当劳、必胜客、肯德基,不管是火车站还是旅游景点,拿出手机出示即可打折,超划算,为我省下了不少的银子。

3、谷歌拼音输入法

我喜欢干净清爽的谷歌拼音输入法,它不会偷偷地上传个人信息。

4、SMS Backup +

我是一个喜欢怀旧的“老人”,等老到哪也去不了可以翻看年轻时的记忆。

SMS Backup +是一款短信备份应用,能够把手机的短信备份到Gmail邮箱中。

5、WordPress

因为博客是用WordPress搭建的,所以手机上要装个WordPress应用。其实偶尔用手机写篇文章也是不错的事情。

6、Superuser

这个应该是我拿到手机以后第一个要安装的应用了。它能够让你获得手机的超级权限,干些意想不到的事情。

7、SmartHosts

我们不得不经常更新Hosts列表,SmartHosts能给你创造一个经济实惠的上网环境。

8、RockPlayer Lite

超级视频播放器。

9、FeedMe

谷歌阅读器挂了之后,我就转移到Feedly了,可是Feedly提供的安卓应用要多烂有多烂:加载慢到死、不支持离线阅读。

FeedMe的横空出世让我欣喜不已,它能同步Feedly的条目到安卓客户端,速度快,支持离线阅读,无广告,而且支持包括全文分享的多种分享方式。

10、ES任务管理器

赶紧扔掉那些卫士和大师吧,给你介绍一款小巧玲珑的应用。ES任务管理器可以清理缓存、结束进程、电量管理。

当然还有其他大众的应用,包括Gtalk、Gmail、Map、QQ、Opera、微信。

2013年6月29日星期六

使用PS制作1寸照的步骤

首先我们需要知道所做照片的尺寸,1寸照片的参数为:尺寸2.5厘米×3.5厘米,分辨率300像素/英寸。使用PS制作1寸照的步骤如下:

1、Photoshop打开待处理的照片。

2、使用各种方法处理、美化照片。

3、调整照片到1寸照的标准尺寸。PS菜单栏中选择“图像”→“图像大小”→勾选“约束比例”→“高度”填3.5厘米→“分辨率”填300像素/英寸→“确定”。

4、接着裁剪图像。参数为宽度2.5厘米,高度3.5厘米,分辨率300像素/英寸。裁剪的结果即为标准的1寸照尺寸。

5、照片加白边。菜单栏“图像”→“画布大小”→宽度和高度各增加0.2厘米,也就是设置宽度为2.7厘米,高度为3.7厘米。

6、菜单栏中“编辑”→“定义图案”。

7、把一寸照片放在画布中。先设置画布的宽度和高度,宽度为2.7×4厘米,高度为3.7×2厘米,也就是说画布上的照片分2行排列,每行放4张照片。Photoshop“文件”→“新建”→ 宽度为10.8厘米,高度为7.4厘米,分辨率300像素/英寸。

8、“填充”→使用“图案”,“自定图案”选择第6步的定义图案,“模式”正常,“不透明度”100%.

9、图片另存为,然后在打印机中打印就可以了。

2013年5月10日星期五

Excel表格数据引用(合并)的方法

有时候我们在制作Excel表格的时候需要引用另外一个Excel表格的数据,这时我们需要vlookup函数来帮忙。下面用一个简单的实例说明该函数的使用方法。

sheet1

sheet1

sheet2

sheet2

我们想要的结果是把sheet2中学生学号对应的成绩填入相同学号的sheet1当中去。现在我们先来填张三同学的成绩,鼠标点击张三的成绩栏。在函数区域输入以下内容:=VLOOKUP(A2,Sheet2!$A$2:$B$7,2,FALSE)

vlookup函数

解释一下这个函数的功能,我们想在这里填入张三的成绩,A2表示要查找的条件,这里他的值是1001,我们要查找学号1001的成绩。Sheet2!$A$2:$B$7,2表示查找的范围,张三的成绩要从sheet2表的A2到B7之间的范围内查找。2表示查找的结果所在列,这里成绩在sheet2表的第二列,所以填“2”, FALSE表示非顺序查找。

输入完成以上的内容然后“回车”,张三的成绩就会显示出来了。

其他同学的成绩你也可以按着上面的方法来输入,比如王二的成绩的函数为=VLOOKUP(A3,Sheet2!$A$2:$B$7,2,FALSE).区别就是王二的学号1002在sheet1的位置是A3.

当然其他同学的成绩不用一一输入函数来获得,可以利用“格式复制”来获得,将鼠标点击张三成绩处,放在又下角鼠标指针变成“+”时,顺势按下鼠标左键往下拉。

格式复制

下面就是我们所要得到的结果。

结果

下面是这个小实例的下载地址:Excel表格数据引用.xls

2012年12月13日星期四

VB使用ADO操作Access数据库简单实例

这里只是个简单不能再简单的VB小程序实例,但它包含这几个关键字:VB6.0、ADO、Access

环境:visual basic 6.0 企业版(非精简版,不然会缺少必须的控件)

数据库:Access数据库,数据库是xs.mbd,内建表为xj

结果:vb使用ADO连接access数据库,查询xj表中的所有数据,然后把查询到的结果循环输出到窗口中。

代码:

Private Sub Form_Click()
Dim db As New ADODB.Connection, RS As New ADODB.Recordset 'ADO连接对象和记录集
Dim strSQL As String 'SQL字符串
db.ConnectionString = "provider=Microsoft.Jet.OLEDB.4.0;Data source =" & App.Path & "/xs.mdb" '数据库连接
db.Open '打开数据库

strSQL = "select * from xj" 'SQL字符串
RS.Open strSQL, db, 3, 1 '查询数据表
Do While Not RS.EOF '循环输出查询到的结果
Print RS!姓名; RS!性别; RS!班级; RS!出生年月 '在窗口中打印输出结果
RS.MoveNext '记录下移
Loop
RS.Close '关闭记录集
Set RS = Nothing
End Sub

源代码下载地址:vb_ado_access.zip