解惑

解己之惑,解人之惑

分类:.net (第2页共4页)

Interop的dll

底层是COM,但是会自动生成Interop的dll给.net平台用,问题是用regsvr32注册COM的时候好像不会更新那个Interop出来的DLL,遇到一个问题就是这个导致的,编译没有问题,运行的时候死活找不到新加的那个类,后来没有办法,搜索整个计算机,把COM的DLL和Interop的DLL全部搜索出来并且删除,再看Visual Studio,才发现它实际上使用的是c:\windows\assembly\GAC_MSIL下的那一份,你在搜索的时候把搜索系统文件和隐藏文件都勾上也不会去搜索这个目录下的东西。应该是有命令可以更新的,不过我现在还是暴力替换:

c:

cd \windows\assebmly

attrib -r -h -s Desktop.ini

del Desktop.ini

这样这个目录就可以进去看并且直接替换DLL了。

Exchange的Journal邮件

需要做Journal邮件的过滤,从Outlook里面看到的情况是,发件人是Microsoft Exchange on behalf of Xxx,而且正文是Journal Report,原始的邮件信息被作为附件了。开始还郁闷怎么弄,不过用SourceOne创建了Journal Activity以后,发现可以正常的处理,From得到的还是原始的发件人,而不是那个Microsoft Exchange on behalf of Xxx,邮件正文还是原来的邮件正文。不知道是SourceOne处理了这个问题还是。。。

调试进程

说实话,这个特性是我做windows开发以来最为赞赏的一个微软的功能。按照一个现在的同事好友的说法(他以前是微软的,铁杆的微软派),只要你有PDB和源代码,你就可以调试任何进程,从目前我的试验来看,此言不虚,而且做起来也不难:

  • 打开一个新的Visual Studio(我用的2005)
  • 选择Tools->Attach to Process
  • 选择你想调试的进程,在选择的时候注意可能要修改Code Type,就我们的项目而言,外壳是C#的,但是调用的都是C++写的COM,所以我把Code Type从自动修改成Managed和Native。
  • 在自动打开的Modules里面选择你需要调试的module,就是load symbol(其实也可以通过Tools->options->debugging->symbols设置全局的symbol,这样就不用每次debug的时候手动的load symbol了),其实就是PDB文件
  • 打开源代码,不需要创建任何工程或者Solution,在进程的操作会触发的地方设置一个断点,等待或者手工触发那个断点的路径

调试COM

对于熟悉的人而言,这个可能不是什么问题,但是对于我这个.net菜鸟和其它的菜鸟,可能还是有用的。

我们新的项目是基于.NET开发的,而我们要调用或者说依赖很多C++的COM组件,我们有COM的源代码,我们的.NET代码在调用COM的时候经常会有问题,但是我们想知道到底是什么问题,这样就需要跟踪进COM里面,详细的步骤在这里:
http://support.microsoft.com/kb/919519
这个KB是How to debug a COM+ component by using Visual Studio 2005 or by using Visual Studio .NET

不过这个KB还不够,它指出了原理性的东西,但是还有些细节没有说:
如果你的工程是C#的工程或者是其他的.NET的工程,那么需要修改工程的debug属性,把Enable unmanaged code debugging选中(如果不选中这个,那么会出现the symbol file does not match the module,即使其实他们是match的)。
那个KB很长,其实重点就是两个:

  • 在Solution的属性里面,把COM的源代码的目录加进去
  • 在VS的选项里面,把COM的symbol加进去,这样就不用在你自己的代码里面设断点再load symbol了

另外文章中的那个加载dllhost那个进程的操作似乎是不需要的,我现在没有操作,可能那个操作对调试COM+有用,对于普通的COM不需要。

TechNet是个不错的选择

和同事聊天的时候说到盗版的Windows操作系统,他们问我为什么不用MSDN Account,我们是新的team,开始的预算可能比较少,目前只从公司申请到两个帐号,然后抽签,其他人抽中了,没我的份。
然后大家又聊了下KEY的使用期的问题,然后我回来搜索了下,发现即使帐号到期,那些生成的KEY依然是可以继续使用的,即使原来从来没有激活过。只要你不把这些KEY用在生产环境(应该就是运营中的服务器)。

回来搜索了下,开始没有搜索到怎么买MSDN Account,倒是搜索到TechNet,感觉很像,又看了下价格,如果是在线下载软件的话,只需要2823,而且有时候还可以打个折(搜索到现在进行中的一个活动是可以打六折,但是好像有限制),如果是这样的话,肯定比单独买OS和Office便宜很多(当然,现在这些也卖得比原来便宜多了)。
后来又搜索了下MSDN Account,发现和TechNet差不多,比它多一些,主要就是Visual Studio系列,但是价格就高得多,要1999美刀,我们公司好像一个Premium帐号只要7000多一点吧,估计有些零售商也能够拿到比这个低的价格,不然人家怎么活啊。

虽然我现在工资不低,但是要我花2000刀买这个的话还是很不舍得的,肯定宁愿买MBA了。什么时候我良心发现,可能可以考虑买个TechNet,不过估计老婆不会同意

导入的Reference不能编译

在工程中导入一个Web Service,发现竟然有编译错误,其他的工程没有问题,后来发现是因为工程的Namespace和工程的Service同名,也就是说,工程可能叫MyService,而创建的那个Web Service也叫MyService,所以创建出来的默认的namespace也是MyService,而VS创建的Web Service的stub会引用原来的namespace,所以就会导致引用MyService这个名字,但是编译器不知道你要找这个namespace还是类。因为处于同一个namespace里面的时候可以只用短类名就行了,但是生成的stub是使用全限定名的。

因为这个鄙视一下微软,因为这个是它推荐的命名规范导致的,而Java,package的名字推荐全部使用小写,而类名单词首字母大写,这样就不会出现类似的问题了。

EveryOne不是真正的EveryOne

还是持续集成的问题。Nant中使用copy拷贝文件到远程的机器,远程机器创建了目录并配置成EveryOne是FullControl的,结果是不能删除也不能创建文件,如果运行Service的帐号是默认的那个用户(SYSTEM\NetWorkService),但是如果修改安全策略,让EveryOne可以FullControl服务的话到是没有问题的。
所以说,都是微软的功能,都是EveryOne,都是FullControl,但是对不同的用户,这个EveryOne还是有区别的,似乎文件访问的控制更加严格一些。
另外,环境是虚拟子网里面的东西,我从我自己的机器上(完全不在一个子网和域里面)访问那些共享目录倒是可以删除和创建东西,好奇怪啊。

远程控制Service

刚刚还说要写powershell去远程控制service,结果google了下就发现有现成的命令SC:

sc \\targetServer start IISAdmin

唯一的问题就是权限了,运行sc的用户需要有远程机器的高级权限,最好是Administrator,所以最好用域的Administrator

更新:
关于权限的,前面说了用Administrator,但是有些东西不受你自己控制,例如我们,用的Teamcity,虽然我修改了TeamCity和Agent的用户身份,但是很抱歉,不好使。最后只能按照微软的KB修改安全策略,使用的是Security Templates,把IIS相关的三个服务(IISAdmin, HTTPFilter, W3SVC)的Full Control权限分配给了EveryOne。

再更新:
按照微软的KB修改安全策略修改时需要很小心,在打开Database的时候,如果是新的,会提示你选择Security Template,如果你选择的Template不对,那么修改后应用的时候可能会覆盖其他的安全策略,目前我也没有发现正确的应该是什么。所以,请慎用!

最后更新:
知道应该怎么修改当前的安全策略了,把C:\WINDOWS\security\Database\secedit.sdb复制一份,然后打开Database的打开复制的那个,原始的那个不能直接打开。再次鄙视一下微软,这个KB写得实在不怎么样,连提醒都不提醒,另外,Configure Computer Now的时候,应该可以只应用修改的某些项,没有修改的就不要动。

思路不能太僵化

原来的一个项目是Java的,构建的自动发布是采用的FTP+SSH,用FTP把文件上传到目标服务器,然后SSH登录过去重启Service使得新的Deploy生效
现在换到.Net下了,思路没有变,因为有原来的成功经验在啊。
先搜索了下,发现NAnt虽然不支持FTP,但是有第三方的东西支持,下载了,但是发现不好使。
去上了趟厕所,突然想到,我的目的是把文件拷贝到目标目录,为什么不用文件共享呢,这个最简单了,Windows直接支持,不需要任何额外的东西。
至于SSH,估计NAnt也是不支持的,但是powershell是支持远程控制其他的计算机的,重启个服务应该还是很简单的,还没有试,明天再弄了。

.NET平台下的持续集成

比Java平台下的麻烦太多。光是一个Unit Test就折腾了很长时间,很多都推荐NUnit,但是用Visual Studio还得让大家都安装NUnit,也为了看看完全用微软的方案是否可行。
由于我们现在的持续集成的工具选的是TeamCity,所以主的build脚本只能基于NAnt,因为TeamCity虽然支持MSBuild或者VS,但是没有对应的Runner或者兼容的Agent,所以基本上等于不支持。
从NAnt里面调用VisualStudio的工程文件编译是没有问题,因为有nantcontrib,但是运行Unit Test就成问题了,google了很长时间也没有找到好的解决方案,有人自己写了dll去掉整个solution的unit test(微软的msunit),还有个Gallio项目,都不怎么好用,最后回到起点:使用命令行的方式,但是需要在TeamCity的机器上安装Visual Studio,还好我们是大企业版,随便装。
最后出来的build.xml:

<?xml version="1.0"?>
<project name="POC" default="build" basedir=".">
    <property name="nantcontribdll" value="c:/nantcontrib-0.85/bin/NAnt.Contrib.Tasks.dll"/>
    <property name="mstestcommand" value="C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\MSTest.exe"/>
    <property name="unittestdir" value="unittest"/>
    <property name="outputtype" value="debug"/>
   
    <target name="build" description="compiles the source code">
        <loadtasks assembly="${nantcontribdll}" />

        <msbuild project="MyProject\MyProject.csproj">
                <property name="teamcity_dotnet_use_msbuild_v35" value="true"/>
        </msbuild>
        <msbuild project="MyProjectTest\MyProjectTest.csproj">
                <property name="teamcity_dotnet_use_msbuild_v35" value="true"/>
        </msbuild>
    </target>
   
    <target name="unittest" description="Run unit test" depends="build">
        <delete dir="${unittestdir}" />
        <mkdir dir="${unittestdir}" />
       
        <exec program ="${mstestcommand}" commandline="/testcontainer:MyProjectTest\bin\${outputtype}\MyProjectTest.dll /resultsfile:${unittestdir}\MyProjectTest.trx" basedir="MyProjectTest"/>
    </target>
   
    <target name="clean" description="Clean output">
        <loadtasks assembly="${nantcontribdll}" />
        <delete dir="${unittestdir}" />
        <msbuild project="MyProject\MyProject.csproj" target="clean">
                <property name="teamcity_dotnet_use_msbuild_v35" value="true"/>
        </msbuild>
        <msbuild project="MyProjectTest\MyProjectTest.csproj" target="clean">
                <property name="teamcity_dotnet_use_msbuild_v35" value="true"/>
        </msbuild>
    </target>
</project>

对于NAnt需要特别说明的是:在TeamCity里面可以用NAnt0.85版本,但是本地调用的话必须用NAnt0.86beta1(当前最新版本),只有这个版本支持.net3.5,而TeamCity使用自己的方式支持.net3.5,就是我们看到的丑陋的teamcity_dotnet_use_msbuild_v35,不能定义一个全局的property了事,必须在每个msbuild任务里面定义这个property。

更早的文章 更新的文章

© 2024 解惑

本主题由Anders Noren提供向上 ↑