多文件批量上传

用一个页面实现文件上传,一般只需要使用HtmlInputFile的runat=server版本就行了,但是现在有些不同的地方:
1、直接上传到数据库的image类型的字段中,而不产生本地文件;
2、多个文件同时上传;
3、上传的文件组最后要同其他相关信息进行关联;

解决方法主要有两种:
1、每次上传一个文件到临时目录,返回并保存相关信息到ViewState,最后提交的时候,统一将文件写入数据库,并根据相关信息做关联;
2、每次上传一个文件到数据库,返回并保存相关信息到ViewState,最后提交的时候,根据相关信息做关联;
3、每次采集HtmlInputFile中的信息到ListBox,最后统一上传多个文件,并做相关关联;

无疑,第三种是其中最好的一种,但是上传多个文件却比较麻烦,本来想在提交的时候,分别多次设置 HtmlInputFile.PostedFile.FileName属性,再多次调用SaveAs进行上传,但在一次提交过程中它不允许重设 FileName属性(事后想想,确实应该不行:P)
后来又想在后台动态添加HtmlInputFile控件并且设其Visible属性为false,结果好像还是不行,因为还是不准自己指定那个怨念的FileName属性

结果:
增加文件按钮:
if( null == m_htmlInputFile )
m_htmlInputFile = new ArrayList();
m_htmlInputFile.Add( FileInputField );

其中FileInputField为System.Web.UI.HtmlControls.HtmlInputFile类型;
并且注意设置m_htmlInputFile这个ArrayList为static,以防每次增加文件后被刷新为null:(
这里其实就每次Add那个Html控件就行了,他们都对应相同的html控件,但是后台的对象每Add一次增加一个:)

提交按钮:
if( null == m_imageList )
m_imageList = new ArrayList();
if( null == m_imageTypeList )
m_imageTypeList = new ArrayList();
foreach( HtmlInputFile hif in m_htmlInputFile )
{
System.Drawing.Image image = System.Drawing.Image.FromStream( hif.PostedFile.InputStream );
m_imageList.Add( image );
m_imageTypeList.Add( hif.PostedFile.ContentType );
}

显示图片:
在GetImage.aspx?ImageID=*页面的Page_Load中
Response.ContentType = m_image.ImageType;
Response.BinaryWrite( m_image.Img );

注意采用BinaryWrite以及设置ContentType为image/pjpeg等

最后在保存文件到后端数据库的时候有点小不爽:
MemoryStream ms = new MemoryStream();
image.Save( ms, System.Drawing.Imaging.ImageFormat.Jpeg );//image是System.Drawing.Image
m_image = new byte[ms.Length];//m_image是byte[]
ms.Position = 0;
//If Too Long, ...
ms.Read( m_image, 0, Convert.ToInt32(ms.Length));

这里ms.Length是long类型,但是同一个类-MemoryStream的Read方法的第三个参数是int型,涉及到一个向下的类型转换,如果Length过大,应该这里会有问题,不知是怎么回事:(

发布Web Services

笔记本上Release后一切正常的Web Services,部署到另外一台2003的服务器上,出现两个问题:

1、Critical Error:

…没有权限访问注册表

其实只是在写入EventLog的时候ASPNET的权限不够,不过奇怪的是把ASPNET和匿名帐户加入Administrator组,重启,好像权限还是不够>.<

查看其列出的跟踪堆栈,发现好像是Enterprise Library中ADO.NET连接数据库的问题,在网上查了查,有用的文章不多,最后居然就在EntLib的FAQ里,发现是没有正确部署EnterLib程序集的问题。

安装程序工具(Installutil.exe)
允许通过执行指定程序集的安装程序组件来安装和卸载服务器资源。
注意: 在“%windir%Microsoft.NETFrameworkv1.1.xxxx”中可以找到Installutil.exe,其中xxxx是您使用的 .NET Framework 的内部版本号。

Installutil Microsoft.Practices.EnterpriseLibrary.Common.dll
Installutil Microsoft.Practices.EnterpriseLibrary.Configuration.dll
Installutil Microsoft.Practices.EnterpriseLibrary.Data.dll

一切恢复正常。

不过还是不知道为什么他的程序集部署的时候必须Install,而自己的dll就不用这一步。

PS:
删除用
Installutil /u xxx.dll

2、localhost访问没有问题,但用www.xxx.com访问,出错

在 .NET Framework 1.1 远程环境中,默认情况下 HTTP GET 和 HTTP POST 同时被禁用。这是出于安全方面的考虑。
当 Web 服务升级到 .NET Framework 1.1 后,应用程序使用 HTTP GET 或 HTTP POST 调用 Web 服务时会失败。
这些应用程序会收到以下一条错误信息 System.Net.WebException指出无法识别请求格式。

由于使用POST,现在已基本不可能转成SOAP协议,只有将其打开,更改Web.Config文件:
<configuration>
<system.web>
<webServices>
<protocols>
<!--
<add name="HttpGet">
-->
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>

Bug in Enterprise Library

TNND,最近在用Enterprise Library的时候,需要自己实现他的IAuthorizationProvider接口,然后在用他的配置工具(EntLibConfig.exe)进行配置的时候,老是提示:

The type name XXX is not valid.

但是我看了几百遍,还是觉得应该实现方式没有什么问题。好在Enterprise Library带有源码,我直接把他配置工具的下面行注释掉:

// errors.Add(instance, name, SR.ExceptionTypeNotValid(typeName));

于是一切使用正常,说明确实没有问题。但心中总是不爽。

今天在网上翻,终于发现,果然是微软的一个bug….

The problem is that some of the configuration settings have the [TypeValidation] attribute, which will attempt to check that the assembly qualified name of the type is a valid type. Unfortunately, this is running in an App Domain which is rooted in the EntLibConfig.exe directory, and so will only be able to resolves types in assemblies in that directory, or in the GAC.

而且提供的暂时解决方案居然就是直接注释掉那一行,他还友情提醒,因为没有检测,自己注意类型不要弄错了- –

唉…郁闷- –

所以,如果确实不想改动源码,可以直接把生成的DLL,用生成后事件copy到EntLibConfig.exe目录下就行了。

破解发布—DynAdvance Notifier

DynAdvance Notifier

很好用的一个咚咚,支持hotmail,gmail,pop3,imap,yahoo
最新版本1.1.68,本来一直用的1.0.6,感觉也和现在差不多,而且网上也有破解版。

不过…唉…一直喜欢追求小版本号,弄得试用期过了收发邮件一直不方便。
附件里是天天破解版:)目前网上在我的搜索能力范围内应该还没有破解吧,要不我也懒得自己弄了:)所以顺道贴出来。

注册号随便写就行了。很久没有碰过这些了,现在只会一个劲暴破了,希谅:(

http://www.dynadvance.com/

Download Cracked Dynadvance Notifier

[求助]无语了,Fucking VC++6.0[Done]

以前之所以选择BCB,就因为那VC++6.0看来确实面目可憎,外加那Fucking MFC…
但那怨念的BCB居然和IBM一个最新驱动冲突,而鄙人又是一个可耻的追求小版本号的淫,于是乎…

调了半天,下面的代码还是不对,GetProcAddress始终返回0,而hmod根据调试,应该取得了正确的值
唉,还望各位达人,帮助小弟- –

/*
Foobar.exe
*/
#include <stdio.h>
#include <windows.h>
__declspec(dllexport) int Mom()
{
printf("Fuck VC++n");
}
int main()
{
HMODULE hmod;
typedef int (* FOO)();
FOO foo;
hmod = LoadLibrary("Foobar.exe");
if(hmod != NULL)
{
foo = (FOO)GetProcAddress(hmod, "Mom");
return -1;
}
if(foo)
foo();
}

任务稿:IIS6+SSL Based On 2k3

IIS提供了SSL安全加密传输功能,如下配置:

1、证书请求文件生成:

进入“控制面板→管理工具→Internet 信息服务(IIS)管理器”,在IIS管理器窗口中展开“网站”目录,右键点击要使用SSL安全加密机制功能的网站,在弹出菜单中选择“属性”,然后切换到“目录安全性”标签页,接着点击“服务器证书”按钮。在“IIS证书向导”窗口中选择“新建证书”选项,点击“下一步”,选中“现在准备证书请求,但稍后发送”,接着在“名称”栏中为该证书起个名字,在“位长”下拉列表中选择“密钥的位长”,这里要注意,位长不能设置的过大,否则会影响通信质量;接着设置证书的单位、部门、和地理信息,在站点“公用名称栏”中输入该网站的域名,然后指定证书请求文件的保存位置,这里笔者将该证书请求文本文件保存在 “certreq.txt”。这样就完成了证书请求文件的生成。

2、安装证书服务:

在“控制面板”中运行“添加或删除程序”,切换到“添加/删除Windows组件”页,在“Windows组件向导”对话框中,选中“证书服务”选项,接下来选择CA类型,这里笔者选择“独立根CA”,然后为该CA服务器起个名字,设置证书的有效期限,建议使用默认值“5年”即可,最后指定证书数据库和证书数据库日志的位置后,就完成了证书服务的安装。

3、使用证书请求文件申请证书:

运行Internet Explorer浏览器,在地址栏中输入“http://localhost/CertSrv/default.asp”。接着在“Microsoft 证书服务”欢迎窗口中点击“申请一个证书”链接,然后在证书申请类型中点击“高级证书申请”链接,在高级证书申请窗口中点击“使用BASE64编码的 CMC或PKCS#10文件提交…”链接,接着将证书请求文件的内容复制到“保存的申请”输入框中,这里笔者的证书请求文件内容保存在 “certreq.txt”,最后点击“提交”按钮。虽然完成了IIS网站证书的申请后,但这时它还处于挂起状态,需要颁发后才能生效。

4、颁发证书:

在“控制面板->管理工具”中,运行“证书颁发机构”程序。在“证书颁发机构”左侧窗口中展开目录,选中“挂起的申请”目录,在右侧窗口找到刚才申请的证书,鼠标右键点击该证书,选择“所有任务→颁发”。

5、备份证书:

打开刚刚颁发成功的证书,在 “证书”对话框中切换到“详细信息”标签页。点击“复制到文件”按钮,弹出证书导出对话框,一路下一步,在“要导出的文件”栏中指定文件名,这里笔者保存证书路径为“backup.cer”,最后点击“完成”。

6、使用证书:

进入“控制面板->管理工具->Internet 信息服务(IIS)管理器”,在IIS管理器窗口中展开“网站”目录,右键点击要使用SSL安全加密机制功能的网站,在弹出菜单中选择“属性”,然后切换到“目录安全性”标签页,接着点击“服务器证书”按钮。使用“IIS证书向导”窗口配置SSL,注意端口的选择,默认443。

关于C#一个基础问题的初步探查

关于C#一个弱弱问题的初步探查

在书上看到这样一个例子:

已知:
interface IControl
{
void Paint();
}
class Control : IControl
{
public void Paint(){ ... }
}
class TextBox : Control
{
new public void Paint(){ ... }
}

问:
IControl it = new TextBox();
it.Paint(); //调用哪个Paint()?

书上的结论是Control::Paint(),并且吹了一通什么没有virtual关键字或者让TextBox直接继承至IControl就是静态决议,什么如果Control::Paint()加上virtual又怎么怎么,如果TextBox::Paint()去掉new又怎么怎么,感觉甚是繁琐、复杂和多变,让人如坠万丈深渊,万劫不复…(- -)

就我原来从C++带来的理解:IControl是个interface,其实隐含IControl::Paint()是abstract 以及 public,只是不能显式写出;所以成员函数的调用决议应该是运行期完成,也就是说为TextBox::Paint();

实际上机测试结果,令人汗颜,他的结果的确是正确的,但是他的后续所有解释都是错误的;不管如何加virtual、去掉new,最后的结果都是一个—Control::Paint(),程序代码如下:
using System;
namespace TestInterface
{
interface IControl
{
void Paint();
}
class Control : IControl
{
public void Paint()
{
Console.WriteLine("Control::Paint()");
}
}
///

/// TextBox 的摘要说明。
///

class TextBox : Control
{
new public void Paint()
{
Console.WriteLine("TextBox::Paint()");
}
}
///

/// TestInterface 的摘要说明。
///

class TestInterface
{
///

/// 应用程序的主入口点。
///

[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
IControl it = new TextBox();
it.Paint();
}
}
}

如果去掉new当然仅仅会导致警告,实际上还是覆盖。

书中还提到“我们的误解来自一个假设:Control::Paint()被自动视为vitrual”,根据实际上机测试,这个假设的确是成立的,而不是什么误解,至于加上virtual和去掉virtual所带来的区别仅仅在于是否加入关键字final。如果没有加上了virtual,那么Control::Paint()会自动视为final(IL中),有例为证:

Contorl::Paint()
.method public hidebysig newslot virtual final //如果加上vitrual则这里去掉final
instance void Paint() cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: ldstr "Control::Paint()"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method Control::Paint
TextBox::Paint()
.method public hidebysig instance void Paint() cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: ldstr "TextBox::Paint()"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method TextBox::Paint

而在Main()中仅是简单调用IControl::Paint()

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// 代码大小 13 (0xd)
.maxstack 1
.locals init ([0] class TestInterface.IControl it)
IL_0000: newobj instance void TestInterface.TextBox::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt instance void TestInterface.IControl::Paint()
IL_000c: ret
} // end of method TestInterface::Main

===== 华丽的分割线 =====
呵呵,以上就是我初步的分析,特别混乱,不要见笑,下面我做个总结(个人意见、仅供参考)

原来的C++到C#,在函数重载这一块有一个很明显的区别,那就是override关键字。如果重载必须显式的指明override关键字,如果没有,将隐藏基类成员。这点是很自然的,但是本例的特别之处在于interface的引入。

—– interface —–
interface默认为abstract类,但是和普通abstract类不同的是,他并没有派生自System.Object;其内接口也默认为abstract virtual如下:

.class interface private abstract auto ansi IControl
{
} // end of class IControl
.method public hidebysig newslot abstract virtual
instance void Paint() cil managed
{
} // end of method IControl::Paint

之所以interface被默认为public(指其内接口,而interface本身可以不为public),abstract就不用解释了,但是明示出来反而会出错;
—– interface end —–

—– interface implement —–
.class private auto ansi beforefieldinit Control
extends [mscorlib]System.Object
implements TestInterface.IControl
{
} // end of class Control
.method public hidebysig newslot virtual final //如果加上vitrual则这里去掉final
instance void Paint() cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: ldstr "Control::Paint()"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method Control::Paint

这里太有趣了(- -,过分了…还是说稍微有点意思)interface接口的实现会在IL中自动加上virtual关键字,而不像刚才书上说的,什么误解,这是为什么呢?因为如果像本例中一样,用IControl调用Paint(),而IControl本身是不会实现Paint()的,所以他的实现必须在IL中以virtual关键字标明,让动态决议的时候,能够考虑到这个实现,不然IControl::Paint()的调用就会出问题。

至于这里提到的final,也是interface implement比较独特的一点。override会使得本身重载基类成员,并且本身成为virtual,所以自己的子类也可以重载自己。在程序中,若想重载基类成员,但又不想让子类继续重载,就会使用override sealed关键字,这里IL中的final关键字实际上就是指的sealed。

由此,我们一般写一个函数:

public void foo();

子类都无法override,除非函数改为:

virtual void foo();

但是这里由于interface implement本身需要申明为override(IL中仍为virtual),所以为了延续惯例,用sealed(IL中为final)封闭之,除非你显示的指示virtual,这样就和我们通常的观念保持一致鸟~~~~
—– interface implement end —–

—– extended classes —–
.class private auto ansi beforefieldinit TextBox
extends TestInterface.Control
{
} // end of class TextBox
extends TestInterface.Control
.method public hidebysig instance void Paint() cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: ldstr "TextBox::Paint()"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method TextBox::Paint

这里不管你是否采用new关键字,实际上都起到了覆盖的作用,只是如果没有new关键字会引发警告,提醒你是否确实是想覆盖,如果你想关闭警告,就必须显示的告诉编译器我想覆盖—就是使用new关键字。

值得一提的有两点:
1、如果程序中直接写virtual而不用override,其实还是覆盖。可以从IL中看出:
程序<->IL
virtual<->newslot virtual
override<->virtual
2、如果这个类直接多重继承IControl,像这样:
class TextBox : Control, IControl
{
...
}

实际上这个类就不再属于extended classes了,而是interface implement。由于对于interface implement的选择是virtual的,所以很自然会调用TextBox::Paint();
—– extended classes end —–

如果以上的讨论正确,本例就很好解释鸟~~~

IControl::Paint()由于是virtual,他会先行寻找可行函数,再进行最佳决议;

由于new关键字的覆盖函数并未override,所以他连可行函数都算不上。自然无论如何都不可能被调用。相反,可能函数只有Control::Paint();

如果让TextBox::Paint()用override修饰(自然Control::Paint()需要用virtual修饰),那么可能函数有Control::Paint(),TextBox.Paint(),其中根据动态决议,最佳为TextBox.Paint();

ZTMD宁愿重写,也不排错

奋战了一个星期的简易登陆系统排错,最后的结果让人汗颜:
将Web.Config里面的
<authentication mode="Windows">
</authentication>

改为
<authentication mode="Forms">
<forms name="TheSky" path="/" loginUrl="/TheSky/WebModules/Users/Login.aspx" protection="All" timeout="30">
</forms>
</authentication>

我一直没有查Web.Config。唉,已经欲哭无泪了,呜呜…

ps:ztmd,ztmD,ztMd,zTmd,Ztmd,ztMD,zTmD,ZtmD,zTMd,ZtMd,ZTmd,zTMD,ZtMD,ZTmD,ZTMd,ZTMD

关于Gmail怨念的附件下载

在Gmail下载了马莞迪的一个附件,同时生成了两个文件,CAG6D4B.和CAG6D4B,改任意一个后缀为DOC后正常浏览,后删除二者,结果只删掉一个,还剩下了一个CAG6D4B.,说找不到文件…

于是怨念的旅程便开始了,先试了各种方法删除之:

在win下查看属性,隐藏和只读,分别改之,提示找不到文件

Dos下:

del /F /ARH ...提示找不到文件
Attrib -rh ...提示找不到文件
ren ... 提示找不到文件

现在意识到问题的严重性,而且听说季翔也不幸中招…..上网查资料,各大Blog,论坛很多地方有和我一样的问题,但是没有任何有用的回复(有人说安全模式下可以删除,结果小白的跑去试,当然不行,提示找不到文件)

接着采用原来屡试不爽的杀手锏:

del. file-pathfile-name... 提示找不到文件

当然再接下来就是国外的网站,因为感觉这些BT的咚咚老外老是厉害一点(应该不算崇洋媚外吧)结果发现根本没有这个问题的内容(后来才发现此问题大概只出现在Gmail处理中文附件的时候,所以老外大概没有机会碰上吧)

至此我已彻底无语,剩下的路不多了:

配ServU将路径指向桌面,然后用FTPRush删除之,提示成功,但没有删除

又发现国内某论坛有人对此有所深入探究,引用如下:

“我在同目录里(桌面)又建立了一个名叫“CAJUWNF5”的文件,名字一样但没有那个点儿。再删除原先那个“CAJUWNF5.”时,轻松成功。然而,新建立这个“CAJUWNF5”却删不掉了。现在它的文件名里没有了点,仍删不掉,也照样不能改名或移动。 ”

唉,他这个想法就比较BT,不过还是没有解决问题,但是倒让人很生疑惑,文中他还提到:

“更糟的是,我又重复了一次原先的操作(从gmail中保存附件),想看看是怎么回事。现在,我的桌面上有两块橡皮膏了。”(我也是这样…)

“毛病出在文件名末尾的“.”上。似乎这个点让NTFS在判别文件时产生了什么循环,以致找不到文件。要是FAT,碰到这种文件,用扇区读写工具(比如 debug)进入分区表,手工就能解决。不知NTFS有没有类似的办法。 ”(想来要是FAT,我也不会用debug改分区表…)

本来想就此打住,上各大论坛发帖询问,结果突然看见了任务栏上196的远程SecureCRT连接,想象要是在linux下用rm -rf说不定可以干掉,说干就干:

配共享,开防火墙(天网,Microsoft,IBM)终于在196上smbclient -L 202.115.22.*看到了桌面的共享,然后rm -rf …轻松干掉

有的时候还是感觉linux好阿