2008年8月25日
最近在研究AVI文件格式的生成问题,碰到以下的问题,找到解决办法,共享如下:
1.生成的文件格式的校验问题:
因为是根据AVI RIFF File Refence这个文档来生成的,所以对错不知道。因此需要一个校验工具。偶觉得有两个工具不错:
a. Gsport这个是暴风影音一类的工具会带的工具。如果格式有错误,它会提示出来。
b.VirtualDub 在这里面点工具菜单里面有十六进制编辑器,按Ctrl+R可以显示出RIFF的树,这样比较容易找出问题来。
2.一切都是按文档的说明来生成的,用播放器来播放是正常的,但是用如上的校验工具来看,里面有错位。在trunck列表里面,发现只有第一个是识别出来,后面的跳了一位无法识别。
经研究发现是存在着奇偶对齐的问题,如果内容是奇数位,那么得在后面补上一位来对齐,但是这一位不能记在这个trunck的长度里面,否则解码器多读了一位可能会引起解码错误。
计划把音频加入,以及功能完善化后,发布DLL供人调用。
2008年8月8日
别的不多说,直接上SQL:
修改时:
update [res].[dbo].[IP] set
ip1 = ID+1
output INSERTED.ID,
INSERTED.ip1
where Country = 'IANA'
插入时:
insert into [res].[dbo].[IP](ID, startip, endip)
output INSERTED.ID,INSERTED.startip,INSERTED.endip
values(234666,'12334', '34445')
删除时:
delete from [res].[dbo].[IP]
output deleted.ID, deleted.startip, deleted.endip
where ID = 234666
2008年7月22日
插件机制附处可见,甚至连很多WEB程序也会有。比如说DZ的论坛,动网的论坛等。在应用程序里面,跑插件的时候,最大的问题有两个:
1.插件的crash引起整个应用程序的crash
2.插件有问题时,修改后,需要停下整个程序,来更换插件。
在这时候,进程外插件的好处就显而易见:因为插件加载在进程外,所以插件crash了,不会影响主进程。同时可以自由地卸载插件。
在.net里面,实现进程外的插件的原理是:让插件跑在和主进程不同的AppDomain里面。
但是跨AppDomain来加载程序集确会有权限的问题,所以不能再像以前加载一个DLL后,去遍历每个类,来看有没有合适的插件在里面。它只能根据已知的类名来加载程序集。所以我先设计一个接口:
public interface IPlugInSum
{
string[] GetPlugIns();
}
在这个接口里面实现对每个插件的描述:
public class PlugInSum :MarshalByRefObject, IPlugInSum
{
public string[] GetPlugIns()
{
return new string[] { "DemoPlugIn.DemoPlugIn", "DemoPlugIn.DemoPlugIn2" };
}
}
在这里面我实现了两个插件。同时强制要求这个描述对象的typename为:DemoPlugIn.PlugInSum。这样主进程里面获取了所有的类名后,就可以一个一个地去把插件加载起来了。
2008年7月3日
最近碰到了一个机子上的项目死活不能和TFS绑定,困扰很久,终于找到解决方案,原因很简单,成因也很简单,但是就是没有看到。
废话少说看原文:原文地址:http://teamfoundation.blogspot.com/2007/12/offline-and-back-again-in-vs2008.html
One of the most painful issues in VS2005 was its quirky offline support.
One of the first features I have checked in Visual Studio 2008 was working offline. And what can I say - it (mostly) rocks!
Let's do it step-by-step.
- You open the solution under source control and there is no connection to the server. What you get is the dialog, indicating offline condition

In Output window pane appears the log message, indicating detailed reason for the offline

Important note: Once the solution is opened offline, next time you open it in Visual Studio the dialog won't appear (but the output pane will show same message every time)

- If you choose to change files in your solution/project when is offline, you will have a message that file is read-only once you save the changes. There is no indication of "under source control" status for offline projects or solutions
Important note: When working offline, you may edit or delete existing files or add new ones, and these types of changes will be supported when going "online" with TFS server. However, file renames are not supported
- Now let's go online. You open solution in VS and you have connection - but tranistion to online will not happen automatically. To sync solution/project back online you should use "Go Online" menu, that available on right-click in Solution Explorer or in "File"->"Source Control" menu.

Once you hit "Go Online" requested, the dialog with changes "Go Online" dialog will appear detailing the changes performed while online. The dialog shows files and
changes (add/edit/delete) performed while offline. You may choose not to pend the changes for specific files (then the file will remain writable, but will not have pending changes).

Important note: If you did not perform any changes while offline, the appropriate message will appear
Once online, the pending changes indications will appear in Solution Explorer.
- If you want to unbind your solution/project from source control, all you need to do is to go to "Source Control"->"Change Source Control" menu. The message will appear asking you whether you want to go online or permanently unbind your solution.
But of course, there were several "
Things I did not like":
- No cancel on Offline dialog - either go offline or ...?
- No indication for source controlled files in Solution Explorer in offline mode (similar to that of VSS) - only read-only flag on file serves as an indication
- "Change Source Control" dialog does not allow one to "Disconnect", you can only "Unbind; so going offline happens only when server is not available
Overall, I should say I liked VS2008 experience very much (especially as compared with previous version). I can feel that feedback on TFS2005 offline experience was not wasted!
2008年6月14日
在开发windows服务的时候,想要连接数据库,可是发现在创建的时候就出错了,看看VCL里面的ADO创建的代码,发现是基于COM的调用的:
FConnectionObject := CreateADOObject(CLASS_Connection) as _Connection;
OleCheck(ConnectionPoint.Advise(Self as IUnknown, FConnEventsID));
所以得在服务启动的时候,初始化一下COM:
CoInitialize(nil);
对应的,在服务停止的时候,需要:
CoUninitialize;
Delphi可以很轻松地开发windows服务,可是调试的时候,确有问题。服务能跑起来,可以把把调试器附加到服务的进程上。如果服务起不来呢?该如何调试呢?
如果直接按F9,则服务只是被创建,还没有起动,就会自已退出去了。
我想到的办法就是让服务以普通程序的方式来运行。
为了使用同一份代码,所以我彩用条件编译的方式来实现,在工程的DPR文件里面加上条件:
DELPHI的VCL可以说是一个很精妙的设计。对于一个普通程序来说,它初始化出来的Application是TApplication,而服务的Application是TServiceApplication,所以在想让服务以应用程序的方式来运行的话,一定得处理单元头:
uses
{$IFDEF RUNASAPP}
Forms,
{$ELSE}
SvcMgr,
{$ENDIF}
在这里,我的条件是RUNASAPP,在调试的时候,我就加上这个条件来编译,在正常发布的时候就把这个条件去掉。
由于要调用服务的ServiceStart方法,所以得定义一个变量:
{$IFDEF RUNASAPP}
var
b: Boolean;
{$ENDIF}
同时,原来的应用程序代码也要改成:
Application.Initialize;
Application.CreateForm(TMyservice, MyService);
{$IFDEF RUNASAPP}
MyService.ServiceStart(nil, b);
{$ENDIF}
Application.Run;
{$IFDEF RUNASAPP}
Readln;
{$ENDIF}
加Readln的目标是不让ServiceStart完成后,就退出程序。
这下,服务也可以和应用程序一样的,按F9后开始调试。
2008年5月4日
曾几何时,服务里面弹出一个窗口到桌面上不再是那么地容易了:以前只要把服务设置为允许和桌面交互就可以直接在服务启动的时候,把一个窗口弹给用户。但是现在在vista(其它的OS 下没有测试,未知)下要弹出这样的窗体,首先会弹出一个提示框提示是否接否一个服务弹出来的消息,点接受后,才会在一个全灰的桌面里面弹出这个窗口。不用想,这样的用户体验,肯定是会被直接PASS。原因很简单,因为不同的用户间的桌面是不一样的,服务用的是System的权限,在vista里面是Session0,而用户的帐户不是这个(肯定大于0)。
看来,想弹出一个窗体,需要另一个程序来作辅助了。解决方案有两种:
- 开发一个程序A在启动的时候,随系统启动,并监控指定文件M,服务S有消息的时候,放在文件M里,A 感受了文件变化了,就去读这个文件里的内容,根据规则来作对应的动作。坏处很明显,当用户为了让系统跑得快的时候,这种自启动文件很容易被砍掉,导致了有些功能莫名奇妙地不可用。
- 同样地,也是开发一个程序A,用CreateProcessAsUser这个API来创建这个A ,并且发送到用户的桌面上去。好处是可以把这个A和服务S 放在同一个程序文件里面,根据不同的参数来启动不同的功能。这样用户除非是删除整个服务,否则不会有部分功能能用,又有部分功能不能用的问题。
现在来看看第二种方案,要想用CreateProcessAsUser这个API ,有这样几个步骤:
1.取得用户的令牌(Token)
2.指定好虚拟桌面
3.调用API创建这个用户进程。
在取得用户令牌的时候,又有几个方法:
1.从用户的进程上去剥
2.先用WTSGetActiveConsoleSessionId得到用户会话ID,再用WTSQueryUserToken这个API去取。
不过在vista下面,服务里面的WTSGetActiveConsoleSessionId这个API得到的总是0,也就是Session0,用这个创建出来的进程,还是属于一个服务进程。(而且这个API是XP以及以后的系统才会提供的,在早点的系统上就会调用失败)所以我们只好从用户的进程上去找,用户登录的时候,一定会有的进程就是:explorer.exe,这样可以遍历所有的进程去找到这个(如果是多人同时登录这个系统里,我也不知道该怎么办了,不知道有没有高人指点一下)。
这样创建出来的用户进程,在进程列表里面可以看到是活动用户的。但是如果在这里面使用一下文件选择框,或是去取一些系统目录,比如说用户的桌面,用户的收藏夹等,都会得到空。这时候因为没有指定用户环境造成的。使用CreateEnvironmentBlock这个API就可以搞定了。
2008年4月25日
用delphi搞了一个小服务,来实现多线程,可断点续传地上下载文件。所有的小块单独跑的时候,都非常正常,但是组装在一起的时候,突然内存暴长一下子占用了1G,引起了缓存的大量开销,频繁的IO读写引起了low CPU的情况下面的系统无法响应。开始的时候以为是里面的一些内存流没有释放引起的,review了一下代码确认没有问题。所以只好让系统再卡一次,把调试器挂到正在跑的服务上。突然发现以下的代码在运行时候,有异常情况出现:
var
packagesStr: string;
I: Integer;
begin
if Length(FPackages) = 0 then
packagesStr := ''
else begin
SetLength(packagesStr, Length(FPackages));
for I := 0 to Length(FPackages) -1 do
packagesStr[I ] := chr(byte(FPackages[I]) + 65);
end;
FPackages 是一个记录每个文件包的状态的枚举值,想要把它系列化后保存起来,为了效率起见,所以用了这么一个小技巧(具体的,让我留到后面再讲)。本来才80几个包,结果在这里的字串长度长得惊人。然后很快地发现了问题:
packagesStr[I ] := chr(byte(FPackages[I]) + 65);
应该是
packagesStr[I + 1 ] := chr(byte(FPackages[I]) + 65);
因为当I=0的时候,引入第一个值:65,把这个字串的指针搞乱了,所以引起了海量内存的使用。
好了,让我们先看看delphi里面的string的结构吧:
string是一个比较有意思的类型,它不仅仅是一个字串那么简单。它的结构的开始是一个指针,指向了直正字串开始的地址,所以sting有一个copy on write的特性,也就是说当字串赋值的时候,两个串都是指向同一个内存块(也就是string[1]这个地址),但是如果串被改的时候,就会复制一份出来改。
再来说说我的这个小技巧:因为我这里可能有几十个包,所以保存成字串的时候,如果是一段一段地加起来,到时候会产生大量的临时变量,引起性能的问题。所以我预算了一下它需要多长,就先把这个长度开出来,然后按位地去赋值。
string还有一个妙用是可以当成stream来使用。以前找了一个base64加密的类,它的参数只能传string,而我想要把一副图片转成base64好让它能在IE里面方便地传到服务器上。于是我就把这个图片读到了一个string里面:
var
stream: TMemoryStream;
imagestr: string;
begin
with TJPEGImage.Create do
try
Assign(FCurrDrawingPad);
CompressionQuality := 80;
stream := TMemoryStream.Create;
try
SaveToStream(stream);
SetLength(imagestr, stream.Size);
stream.Position := 0;
stream.Read(imagestr[1], stream.Size);
Result := StrTobase64(imagestr);
finally
stream.Free;
end;
finally
Free;
end;
关于adobe flash cs3 vista安装出错的问题
症状:在Vista下安装Adobe Design Premium CS3正式版时安装程序初始化就出错了,系统会提示“Internal Error 2739错误”。
官方提供的解决方法:
以管理员权限在cmd命令行中运行(在管理员帐户中):
“regsvr32c:\windows\system32\vbscript.dll ”
“regsvr32 c:\windows\system32\jscript.dll”
2008年4月8日
昨天下班,等了十来分钟才来了758,粗一看,发现是两辆车,前面一辆车人比较多,后面的一车人较少,于是我就不假思索地上了后一辆车,发现很多人下车,于是马上抢到一坐,打开手机看小说.等时间差不多的时候,抬头发现走的路很陌生,心里暗叫不好,上错车了.一问旁人,在别人BS的目光下,证实了此事.于是赶紧上车,还好这个车走的线路和758差不多,只是叉开了5站,于是坐回来,再换758回家.
吃完晚饭后,打电话回家,结果老妈告诉我一个坏消息:外婆上周一去世了.虽然外婆一直卧病在床,但是突然走了,还是很让人接受不了的.
今天上班,换车的时候,发现公交卡怎么换姿势读卡机都没有反应.估计被消磁了.真郁闷.