2009年2月26日 星期四

Windows Installer並未正確安裝或windows update無法更新

公司的網管反應有台測試機win 2000 server,常常中毒,我當時用掃毒程式掃了也沒事,但是過幾天後去看,發現掃毒程式每天不定時都會反應掃到一個病毒BAT_FTPER.C,我再想是不是太久沒windows update了,於是就去更新一下,結果失敗...@@

想裝MBSA看看好了,因為MBSA也會告訴你有哪些更新沒裝,結果跳出下列訊息

無法存取Windows Installer
可能是Windows處於安全模式 或是Windows Installer並未正確安裝
請聯絡您的支援人員

解決辦法

1.若要解決windows update無法更新的問題

 a. 安裝Windows Installer 3.0 Redistributable

 b. 重新開機後,就可以正常更新了


2.若要解決Windows Installer並未正確安裝的問題

 regsvr32 %systemroot%\system32\msi.dll

2009年2月22日 星期日

刪除七天前無效的連線

最近有台SQL Server的CPU使用率常常飆高,觀察似乎是連線的數量太多了,有很多連線是程式使用完沒有close的關係,短時間人手不足,沒法修正程式,只好手動清除啦,不過一個一個清太累囉,還是寫段陳述式來清囉

DECLARE @spid int, @SQLstr nvarchar(128)

--僅針對某個登入來清理囉,所以請自行更換"使用者"
DECLARE spids_cr CURSOR FOR
SELECT sp.spid FROM master..sysprocesses sp
LEFT OUTER JOIN master..sysdatabases sd ON sd.dbid = sp.dbid
WHERE sp.loginame='使用者' AND sp.net_address<>''
and sp.last_batch <= DATEADD(dd,-7,getdate())


OPEN spids_cr

FETCH spids_cr INTO @spid

WHILE (@@FETCH_STATUS=0)

BEGIN

SET @SQLstr = 'KILL ' + CAST(@spid AS varchar)

EXEC sp_executesql @SQLstr

FETCH spids_cr INTO @spid

END

CLOSE spids_cr
DEALLOCATE spids_cr

2009年2月12日 星期四

SMTP 550 5.7.1 not permissions as this sender

如果寄信失敗,結果回傳錯誤碼550 5.7.1 ,錯誤訊息跟下面三種情況一樣的話,表示你使用的發信伺服器,有限制寄件者需與帳號一致喔,意思就是若用我的帳號發信,寄件者就不能設成別人,請檢查你的程式寄件者是不是設的與帳號不同!一般發信若是使用SMTP services來寄信是不會有這種困擾的,因為寄件者就算設不存在的也照樣可以寄!

2009年2月11日 星期三

JAVAMAIL範例2(不需認證的smtp)

這個blogger不允許直接貼上完整的jsp程式碼囉,所以我只列出主要的,記得"<"與"%"還有"%"跟">"是沒有空白的喔

< % @page import="java.util.*" % >
< % @page import="javax.mail.*" % >
< % @page import="javax.activation.*" % >
< % @page import="javax.mail.internet.*" % >


< %
String host = "127.0.0.1";
String receiver = "收件人";
String sender = "發信人";
String subject = "主旨";
String mess = "內文success";

boolean sessionDebug = false;

Properties prop = new Properties();
prop.put("mail.smtp.host",host); //指定SMTP server

Session mailsess = Session.getInstance(prop);
mailsess.setDebug(sessionDebug); //是否在控制台顯示debug訊息

Message msg = new MimeMessage(mailsess);
//設定郵件
msg.setFrom(new InternetAddress(sender)); // 設定傳送郵件的發信人
InternetAddress[] address= {new InternetAddress(receiver)}; // 設定傳送郵件的收件者
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject(subject); //設定主題
msg.setText(mess); //設定內文

//發送郵件
Transport transport = mailsess.getTransport("smtp"); //只支持IMAP、 SMTP和 POP3
transport.send(msg);
% >

2009年2月10日 星期二

JAVAMAIL範例1(需要認證的smtp)

最近mail server升級,結果部分系統的發信機制出了問題,所以需要簡單的範例程式來測一下,但是我不會java,只好上網稍微研究了一下囉,簡單的code卻花了我不少時間研究,分享給有需要的朋友,這個blogger不允許直接貼上完整的jsp程式碼囉,所以我只列出主要的,記得"<"與"%"還有"%"跟">"是沒有空白的喔

< % @page import="java.util.*" % >
< % @page import="javax.mail.*" % >
< % @page import="javax.activation.*" % >
< % @page import="javax.mail.internet.*" % >


String host = "發信伺服器";
String receiver = "收件者";
String sender = "寄件者";
String subject = "主旨";
String mess = "內文";
String username = "帳號";
String password = "密碼";

boolean sessionDebug = false;

//Get system properties
Properties prop = System.getProperties();
prop.put("mail.smtp.host",host); //指定SMTP server
prop.put("mail.transport.protocol","smtp"); //設定傳送協定
prop.put("mail.smtp.auth","true"); //設定是否須smtp驗證

// 產生新的Session
javax.mail.Session mailsess = Session.getDefaultInstance(prop);
mailsess.setDebug(sessionDebug); //是否在控制台顯示debug訊息

Message msg = new MimeMessage(mailsess);
//設定郵件
msg.setFrom(new InternetAddress(sender)); // 設定傳送郵件的發信人
InternetAddress[] address= {new InternetAddress(receiver)}; // 設定傳送郵件的收件者
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject(subject); //設定主題
msg.setText(mess); //設定內文

//發送郵件
Transport transport = mailsess.getTransport("smtp"); //只支持IMAP、 SMTP和 POP3
transport.connect(host, username, password); //以smtp的方式登入mail server
transport.sendMessage(msg,msg.getAllRecipients());
transport.close();
% >

2009年2月5日 星期四

FINDSTR進階用法

想搜尋大量文字檔裡的字串,建議FINDSTR一定要學會用,很方便的喔,我這幾天才知道原來有支援一般表示式呢,使用起來更加強大喔

A.利用/G從指定的檔案取得搜尋字串清單(按我看一下會更了解這怎麼用)
  請把下列的"&"替換成shift+\囉,也就是一條直線的管道符號(因blogger把我字給吃了)

findstr /s /i /G:search.txt d:\*.asp & findstr /v /i /G:exclude.txt > c:xx.log

其中 search.txt 是搜尋字串所在的檔案,d:\*.asp加/s是要搜尋D槽下所有asp的檔案,exclude.txt 是要排除的搜尋字串所在的檔案,xx.log則存放搜尋結果。

B.使用一般表示式(Regular Expression)
 以下是FINDSTR所支援的中繼字元,雖沒有很多,但我覺得很夠用囉


 0.跟著我一起練習,會比較了解喔,先把以下綠色文字複製後存成xx.txt,此例是txt是放在f槽,所以下面的語句請自行依情況變換喔


select * from comp
32165469874
select * from accomplish

select * from Comp
546VDFBSF4545
from
select * from comp
select * from COMP
compare


 1.通常若不知道一般表示式怎麼用,想搜尋comp字串,語句可能會長的像下面這行一樣,但是這樣的執行結果會跑出一些我們不需要的結果,如accomplish與compare,如下圖1的地方
findstr "comp" f:\xx.txt
 2. 若知道一般表示式,可以利用"\<"與"\>"來包住comp,限制該字元開頭跟結尾,就可以只找到你要的,就不會跑出accomplish與compare的結果囉,見下圖2的地方
因為這blog會過濾換行字元,所以指令請見圖吧
 3.若只想搜尋comp字串,但是c又不限定大小寫,就可以用中括號來包含字元集合[Cc],意思就是C或c皆可囉,像"[Cc]omp"就是Comp與comp都可,見下圖3
findstr "[Cc]omp" f:\xx.txt


 4若想找開頭為comp的字串,c不分大小寫,見下圖4
findstr "\<[Cc]omp" f:\xx.txt
 5.若想找結尾為comp的字串,c不分大小寫,見下圖5
findstr "[Cc]omp\>" f:\xx.txt
 6.若想找comp的字串,全部不區分大小寫,見下圖6,其實也是可以用"/i" 的
findstr "[Cc][oO][Mm][Pp]" f:\xx.txt


 8.若想找"from comp"字串,中間有一個空格的,可不能直接用"from comp"喔,那可是會找出from或comp的字串啊,所以得用中繼字".",如"from.comp",但是找出的結果可能會有很多,因為"."是萬用字啊,可以替換成任何字元,如圖8
因為這blog會過濾換行字元,所以指令請見圖
 7. 前面已提過"."表示搜索的條件是任意字元,而"*"在一般表示式中的作用不是任意字元喔,而是表示左側字元可以重複的意思,"*"表示重複的次數可為零次或者多次。所以若搜尋字串中使用".*",表示在那字串中可以夾雜0個,1個或很多個任意字元的喔,見下圖7,"from.*comp"的意思就是"from"與"comp"間可以含一個空白或很多空白的意思,在此例囉


 9.範圍[a-z]這種的我就不介紹,因為用起來怪怪的,似乎有問題,網路上我也查到似乎是各bug(Ranges [a-z] and [A-Z] perform INCONSISTENTLY in 2K/XP)


 10."^" 表示行首,"^from"就表示要找一行開頭必須為"from"的囉,其餘的皆不符合,語句如下
findstr "^from" f:\xx.txt
from

 11."$"表示行尾,"comp$"即表示要找一行結尾必須為"comp"的囉
findstr "comp$" f:\xx.txt
select * from comp
select * from  comp

c.利用for迴圈

 介紹到這,當你已了解我前面介紹findstr使用檔案內容當作搜尋清單及一般表示式這兩種用法之後,你就可以把他們結合起來用囉,搜尋清單的內容使用一般表示式,然後如果你再用上for迴圈的話,就可以作到依收尋字串分成數個搜尋結果檔囉!要不然結果全都導入一個檔,之後若要在分類很麻煩的,不如一開始就作好它!那怎麼用呢?語句如下,是一行喔不是兩或三行!要存成bat檔喔! 請把下列的"&"替換成shift+\囉,也就是一條直線的管道符號(因blogger把我字給吃了)
for /f "tokens=1,2 delims=," %%i in (c:\search.txt) do findstr /S /N /R "%%j" D:\svn_meta\*.j* & findstr /v /i /G:exclude.txt > d:%%i.log

我這邊的例子,假設我想找"from travel"及"from zip"這兩個字串,分別希望搜尋結果是導入travel.log及zip.log,search.txt的內容應該長的像下面這兩行
travel,from.travel
zip,from.zip


若看不懂,建議先看我令一篇For的應用

2009年2月4日 星期三

FOR語句的應用

可能很多人不知道在Batch裡也有迴圈可以運用喔,我個人覺得這功能非常強大,雖然我只會簡單的,但有時可幫助我節省不少工作時間呢!
  可在命令列下"for /?"得到詳細資訊喔

0.基本應用(沒有啟用擴充命令)
 就是手動去指定迴圈範圍,語句如下
 FOR %variable IN (set) DO 指令 [command-parameters]

 例子1:如何快速找出硬碟CDE槽的剩餘可用空間 。
 語句1: 請把&替換成shift+\囉(blogger把我字給吃了)
for %i in (c d e) do @dir %i: & find "位元組可用"
 22 個目錄 6,034,595,840 位元組可用
 15 個目錄 1,634,000,896 位元組可用
 8 個目錄 3,506,417,664 位元組可用
 補充1:@ 只是讓輸出結果不包括 dir命令本身而已

 例子2:參考刪除隨身碟病毒裡的一段,內容意思是解除所有硬碟內的autorun.inf及ntdelet.com的屬性,然後刪除它們並隱藏訊息 。
 語句2:
for %%x in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
attrib -r -s -h -a %%x:\autorun.inf >nul 2>nul&&attrib -r -s -h -a %%x:\ntdelect.com >nul 2>nul
del %%x:\autorun.inf /q /f >nul 2>nul&&del %%x:\ntdelect.com /q /f >nul 2>nul )
 補充2:&&的意思是前面命令成功才接著作後面的命令,各位注意可以用小括號來包更多的命令喔,如果要在批次程式中使用 FOR 指令,請指定 %%variable,而不要指定%variable

1.用/R參數列舉所有目錄
 
語句如下
 FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

 例子3:用for來實現與dir /s /b E:\test\*.txt一樣的結果 。
 語句3:
for /R E:\test %i in (*.txt) do echo %i
 補充3:運用得當就可以對當前目錄下所有檔(包括子目錄裏面的檔)進行操作,像例子4

 例子4:用Subversion版控來管理程式碼時,若要將某各版本全部取出,往往每層目錄裡都含有".svn"的隱藏目錄,對用來上線來說,那些目錄都是多餘的,此時就可以利用for /r來清除這多餘目錄囉。

 語句4:
for /R d:\33 %i in (.) do @if exist %i\.svn rd /s /q "%i\.svn"
 補充4:如果 set 只是單一句點 (.) 字元,它只會列舉樹狀目錄結構喔。然後用if exist來判斷的原因是因為for只是機械化的列舉目錄,在此例底下不一定有.svn目錄,所以加判斷會安全點。最後因為rd /s /q這指令太可怕了,使用前最好先替代成echo看一下,要不然執行錯誤可是很慘的,像是例子3那樣。差點忘了一點,列舉目錄結構會多一層".",像"d:\33\cat\.",但這並不影響執行結果喔。

2. 用/F參數將檔案內容作為迴圈範圍
 語句如下
 
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]

 例子5:假設我有一個jj.txt檔案列表,我想連同檔案目錄的架構一起複製到c槽,檔案列表如下

c:\temp\a1.txt
c:\temp\test\a2.txt
c:\temp\test\f\a3.txt
c:\temp\bbb\a4.txt

 語句5:
for /f %%i in (C:\jj.txt) do (xcopy %%i c:%%~pi /Y)
 補充5:只要是 %~ 開頭的操作符號,都是檔案名的分離操作,具體請看 for /? 或語句7。

3.用/F參數將命令結果當作迴圈範圍
 語句如下
 
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]

 例子6:把date /T輸出的"2009/02/05 星期四"拆掉然後轉換成"2009-02-05"
 語句6:
for /f "tokens=1,2,3 delims=/ " %i in ('date /T') do echo %i-%j-%k
2009-02-05
補充6:此例用到"options"的額外參數,"delims=xxx"指分隔符號的集合,此例分隔符號是"/"與" ",意思是把"2009/02/05 星期四"依分隔符號拆成"2009","02","05"等。"tokens=x,y,m-n"是變數指定的意思,此例是把拆出來的第一個變數指定給%i,第二個給%j,依此類推囉

4. 使用%~來加強完整檔案路徑的分離功能

 直接看語句與結果比較快啦
 語句7:
for /f "delims=" %%i in ("C:\WINNT\system32\drivers\etc\lmhosts.sam") do (
echo.
echo 一個完全符合的路徑名稱 %%~fi
echo 磁碟機字元 %%~di
echo 路徑 %%~pi
echo 檔名 %%~ni
echo 副檔名 %%~xi
echo 路徑只包含短檔名%%~si
echo 檔案屬性 %%~ai
echo 檔案的日期時間 %%~ti
echo 磁碟機字元與路 %%~dpi
echo 檔名與副檔名 %%~nxi
echo 含短檔名的完全路徑 %%~fsi)


一個完全符合的路徑名稱 C:\WINNT\system32\drivers\etc\lmhosts.sam
磁碟機字元 C:
路徑 \WINNT\system32\drivers\etc\
檔名 lmhosts
副檔名 .sam
路徑只包含短檔名C:\WINNT\system32\drivers\etc\lmhosts.sam
檔案屬性 --a------
檔案的日期時間 03/06/26 08:00p
磁碟機字元與路 C:\WINNT\system32\drivers\etc\
檔名與副檔名 lmhosts.sam
含短檔名的完全路徑 C:\WINNT\system32\drivers\etc\lmhosts.sam


5. 用/L參數來指定起始值終值的迴圈範圍
 這個跟一般程式很像囉,語句如下
 FOR /L %variable IN (start,step,end) DO command [command-parameters]

 例子8:假設我想ping一段ip範圍,如11.111.2.115~11.111.2.130,如有回應就印出該ip ok之類的
 語句8: 請把一個的"&"替換成shift+\囉,連續兩個的不用替換(blogger把我字給吃了)
for /L %%i in (115,1,130) do ping -n 1 11.111.2.%%i & find "reply" /i && echo 11.111.2.%%i ok

RealVNC的小技巧

這兩個小技巧,知道的人似乎不多,分享給各位囉

1.如何同時允許兩個連線連入,也就是先連入的不會被後來連入的給斷線喔
 a .執行VNC Viewer後,先不要急著按[OK],先按[Options]

  b .在VNC Viewer Options的設定畫面,先切換到[Misc]頁籤,將[Shared connection]打勾,然後就可以按下[確定],預設是不會打勾的,所以預設是後連入的會把先連入的給斷線囉
 c.就這各設定,很簡單吧

2.VNC如何像遠端桌面一樣,可以一台存成一個捷徑,下次直接點選捷徑就幫你連入呢?

用batch就可以達成囉,將下列兩行存成server1.bat,自行替換IP位址囉,也很簡單

cd "C:\Program Files\RealVNC\VNC4\"
start vncviewer.exe 10.122.2.12

2009年2月3日 星期二

自訂sp_who2加強版

  最近遇到有台DB主機的CPU使用率常常滿載,觀察DB的活動監視器,發現有過多Connection似乎沒有colse,這是不好的現象,那得先找出相關的是哪些Connection囉,SQL 2000本身只提供sp_who與sp_who2這兩個遇存程序來觀察,但都沒提供相關Connection的陳述式的資訊,總不可能再一個一個透過DBCC INPUTBUFFER來查吧,先上網找找有沒有人寫好的加強版,有是有啦,不過不是很合自己用,那就自己來自訂一個吧

--只適用SQL 2000,若要用在2005以後版本請看最後一行
USE [master]
GO
IF object_id('sp_who3') IS NOT NULL
BEGIN
DROP PROC sp_who3
END
GO

CREATE PROC [dbo].[sp_who3]
@loginame sysname = NULL
AS
--參數用法有3種,如下:
--exec sp_who3
--exec sp_who3 '14'
-- 指定spid,只會列出該資料
--exec sp_who3 'active'
-- 指定 ACTIVE。ACTIVE 會從處理序報表中,排除那些等待使用者下一個指令的處理序。
BEGIN

SET NOCOUNT ON

--去除參數頭尾空白
SET @loginame = NULLIF(RTRIM(LTRIM(UPPER(@loginame))), '')

--取得sysprocesses相關資訊後,插入暫存#sp_who3
SELECT sp.spid as 'spid',
sp.status as 'status',
sp.loginame as 'loginame',
NULLIF(RTRIM(LTRIM(sp.hostname)), '') as 'hostname',
sp.blocked as 'blocked',
sd.name as 'dbname',
sp.cmd as 'cmd',
sp.cpu as 'cpu',
sp.physical_io as 'physical_io',
sp.memusage as 'memusage',
sp.open_tran as 'open_tran',
sp.last_batch as 'last_batch',
sp.login_time as 'login_time',
NULLIF(RTRIM(LTRIM(sp.program_name)), '') as 'program_name',
cast('NULL' as nvarchar(255)) as 'eventinfo'
into #sp_who3
FROM master..sysprocesses sp
LEFT OUTER JOIN master..sysdatabases sd ON sd.dbid = sp.dbid

--建立暫存table,儲存dbcc inputbuffer資訊用
CREATE TABLE #inputbuffer (
EventType nvarchar(30),
Parameters Int,
EventInfo nvarchar(255)
)

-- 如果參數指定為ACTIVE則排除那些等待使用者下一個指令的處理序
-- (仿照dbo.sp_who2裡的作法)
IF (@loginame = 'ACTIVE')
DELETE #sp_who3
where LOWER(status) = 'sleeping'
and UPPER(cmd) IN ('AWAITING COMMAND',
'MIRROR HANDLER',
'LAZY WRITER',
'CHECKPOINT SLEEP',
'RA MANAGER')
and blocked = 0

-- 以下是取得額外dbcc inputbuffer的資訊用的
-- 像是T-SQL的內容,這補充dbo.sp_who2所不足的地方
-- cursor Start
DECLARE @spid varchar(30)

DECLARE cur_dbccinputbuffer CURSOR FOR
SELECT CONVERT(VARCHAR(30), spid) FROM #sp_who3

OPEN cur_dbccinputbuffer

FETCH NEXT FROM cur_dbccinputbuffer INTO @spid

WHILE @@fetch_status = 0
BEGIN

TRUNCATE TABLE #inputbuffer

INSERT INTO #inputbuffer
exec('dbcc inputbuffer(' + @spid + ')')

UPDATE #sp_who3
SET eventinfo = (SELECT EventInfo FROM #inputbuffer)
WHERE spid = @spid

FETCH NEXT FROM cur_dbccinputbuffer INTO @spid

END

CLOSE cur_dbccinputbuffer
DEALLOCATE cur_dbccinputbuffer

-- cursor End

IF @loginame IS NULL
BEGIN
SELECT *
FROM #sp_who3
ORDER BY spid
END
ELSE IF @loginame = 'ACTIVE'
BEGIN
SELECT *
FROM #sp_who3
ORDER BY spid
END
ELSE IF isnumeric(@loginame) = 1
BEGIN
SELECT *
FROM #sp_who3
WHERE spid = cast(@loginame as int)
END
RETURN 0
END



若要用在SQL 2005上,請將nvarchar(255)取代為nvarchar(max)即可