About neohope

一直在努力,还没想过要放弃...

Java四种引用方式

最近写了个例子,说明了一下强引用、软引用、弱引用、虚引用的区别。

1、NString.java

package com.neohope.reference;

/**
 * Created by Hansen
 */
public class NString {
    private String name;
    private String value;

    public NString(String name, String value)
    {
        this.name = name;
        this.value=value;
    }

    public NString(String name, StringBuilder builder)
    {
        this.name = name;
        this.value=builder.toString();
    }

    public String Name()
    {
        return name;
    }

    public String Value()
    {
        return value;
    }

    @Override
    protected void finalize()
    {
        System.out.println(">> "+Name()+" finalize called");
        try {
            super.finalize();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

2、TestReferenceA.java

package com.neohope.reference;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

/**
 * Created by Hansen
 * JVM参数:
 * -XX:+PrintGCDetails
 * -Xms6m -Xmx12m
 */
public class TestReferenceA {
    public static void main(String[] args) {
        //申请内存
        Runtime rt=Runtime.getRuntime();
        System.out.println("Total memory is "+rt.totalMemory());
        int MemSize = 1024*1024*1;
        StringBuilder builder = new StringBuilder(MemSize);
        for (int i=0;i<MemSize/8;i++) {
            builder.append("ABCDEFGH");
        }
        System.out.println("Total memory is "+rt.totalMemory());

        //用s00与s01两个大字符串演示强引用与软引用的区别
        NString s00 = new NString("s00",builder);
        NString s01 = new NString("s01",builder);
        //s02与s03演示WeakReference的两种用法
        NString s02 = new NString("s02","s03");
        String key03 = new String("k03");
        NString s03 = new NString("s03","s03");
        //s04演示PhantomReference
        NString s04 = new NString("s04","s04");
        System.out.println("Total memory is "+rt.totalMemory());

        //第1类、强引用的对象,也最常用到的类型,内存不足时JVM将抛出异常也不要释放这些内存
        NString strongRef = s00;
        //第2类、只有软引用的数据,内存不足时JVM会回收这些内存
        SoftReference<NString> softRef = new SoftReference<NString>(s01);
        //第3类、只有弱引用的数据,无论内存是否充足JVM会回收这些内存,也就是弱引用不会影响对象的生命周期
        WeakReference<NString> weakRef = new WeakReference<NString>(s02);
        //WeakHashMap很有用,当key022为null时,s022也就会被GC咯
        WeakHashMap weakHashMap = new WeakHashMap();
        weakHashMap.put(key03,s03);
        //第4类、只有虚引用的数据,一开始refQueue为空,被GC才会有值
        ReferenceQueue refQueue = new ReferenceQueue<String>();
        PhantomReference<NString> phantomRef = new PhantomReference<NString>(s04, refQueue);

        //有强引用时,输出初始化情况
        System.out.println("With strong ref strongRef is " + (strongRef==null?"null":"not null"));
        System.out.println("With strong ref softRef is " + (softRef.get()==null?"null":"not null"));
        System.out.println("With strong ref weakRef is " + (weakRef.get()==null?"null":"not null"));
        System.out.println("With strong ref weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //这里为null,当对象被GC时,会得到虚引用对象
        System.out.println("With strong ref refQueue has " + refQueue.poll());
        System.out.println();

        //去掉初始的强引用
        s00 = null;
        s01 = null;
        s02 = null;
        s03 = null;
        s04 = null;

        //多数情况下,没有来得及GC
        System.out.println("Before gc strongRef is " + (strongRef==null?"null":"not null"));
        System.out.println("Before gc softRef is " + (softRef.get()==null?"null":"not null"));
        System.out.println("Before gc weakRef is " + (weakRef.get()==null?"null":"not null"));
        System.out.println("Before gc weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //null,当对象被GC时,会得到虚引用对象
        System.out.println("Before gc refQueue has " + refQueue.poll());
        System.out.println();

        //强制GC
        System.gc();
        System.out.println("After first gc strongRef is " + (strongRef==null?"null":"not null"));
        System.out.println("After first gc softRef is " + (softRef.get()==null?"null":"not null"));
        //null,weakRef已经被释放了
        System.out.println("After first gc weakRef is " + (weakRef.get()==null?"null":"not null"));
        System.out.println("After first gc weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //与运行环境及GC方法有关,会出现一次有值的情况,然后一直为null
        System.out.println("After first gc refQueue has " + refQueue.poll());
        System.out.println();

        //将key03设为null,强制GC
        key03 = null;
        System.gc();
        System.out.println("After second gc strongRef is " + (strongRef==null?"null":"not null"));
        System.out.println("After second gc softRef is " + (softRef.get()==null?"null":"not null"));
        //null
        System.out.println("After second gc weakRef is " + (weakRef.get()==null?"null":"not null"));
        //empty,由于key被设为空,则会释放掉弱引用对象了
        System.out.println("After second gc weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //与运行环境及GC方法有关,会出现一次有值的情况,然后一直为null
        System.out.println("After second gc refQueue has " + refQueue.poll());
        System.out.println();

        //Finalization
        System.runFinalization();
        System.out.println("After Finalization strongRef is " + (strongRef==null?"null":"not null"));
        System.out.println("After Finalization softRef is " + (softRef.get()==null?"null":"not null"));
        //null
        System.out.println("After Finalization weakRef is " + (weakRef.get()==null?"null":"not null"));
        //empty
        System.out.println("After Finalization weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //与运行环境及GC方法有关,会出现一次有值的情况,然后一直为null
        System.out.println("After Finalization refQueue has " + refQueue.poll());
        System.out.println();

        //申请内存,造成内存不足
        System.out.println("Total memory is "+rt.totalMemory());
        StringBuilder builder2 = new StringBuilder(MemSize);
        for (int i=0;i<MemSize/8;i++) {
            builder2.append("ABCDEFGH");
        }
        NString tmp0 = new NString("tmp0", builder2);
        System.out.println("Total memory is "+rt.totalMemory());

        System.out.println("When mem is low strongRef is " + (strongRef==null?"null":"not null"));
        //null,内存不足时软引用会被释放
        System.out.println("When mem is low softRef is " + (softRef.get()==null?"null":"not null"));
        //null
        System.out.println("When mem is low weakRef is " + (weakRef.get()==null?"null":"not null"));
        //empty
        System.out.println("When mem is low weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //与运行环境及GC方法有关,会出现一次有值的情况,然后一直为null
        System.out.println("When mem is low refQueue has " + refQueue.poll());
        System.out.println();

        //再次申请内存,JMV会内存爆掉
        NString tmp1 = null;
        try
        {
            tmp1 = new NString("tmp1",builder2);
        }
        catch(OutOfMemoryError ex)
        {
            System.out.println("Not enough memory");
        }

        //null
        System.out.println("tmp1 is " + (tmp1==null?"null":"not null"));
        //就算是抛出OutOfMemoryError,仍然不会释放
        System.out.println("When not enough memory strongRef is " + (strongRef==null?"null":"not null"));
        //null
        System.out.println("When not enough memory softRef is " + (softRef.get()==null?"null":"not null"));
        //null
        System.out.println("When not enough memory weakRef is " + (weakRef.get()==null?"null":"not null"));
        //empty
        System.out.println("When not enough memory weakHashMap is " + (weakHashMap.isEmpty() ?"empty":"not empty"));
        //null
        System.out.println("When not enough memory refQueue has " + refQueue.poll());
        System.out.println();
    }
}

3、输出

Total memory is 6094848
Total memory is 6094848
Total memory is 11390976
With strong ref strongRef is not null
With strong ref softRef is not null
With strong ref weakRef is not null
With strong ref weakHashMap is not empty
With strong ref refQueue has null

Before gc strongRef is not null
Before gc softRef is not null
Before gc weakRef is not null
Before gc weakHashMap is not empty
Before gc refQueue has null

After first gc strongRef is not null
After first gc softRef is not null
After first gc weakRef is null
After first gc weakHashMap is not empty
>> s04 finalize called
After first gc refQueue has null
>> s02 finalize called

After second gc strongRef is not null
After second gc softRef is not null
After second gc weakRef is null
After second gc weakHashMap is not empty
After second gc refQueue has java.lang.ref.PhantomReference@15d63da

After Finalization strongRef is not null
After Finalization softRef is not null
After Finalization weakRef is null
After Finalization weakHashMap is not empty
After Finalization refQueue has null

Total memory is 14221312
Total memory is 14221312
When mem is low strongRef is not null
When mem is low softRef is not null
When mem is low weakRef is null
When mem is low weakHashMap is not empty
When mem is low refQueue has null

>> s01 finalize called
Not enough memory
tmp1 is null
When not enough memory strongRef is not null
When not enough memory softRef is null
When not enough memory weakRef is null
When not enough memory weakHashMap is empty
When not enough memory refQueue has null

制作Ubuntu安装U盘

本文以Ubuntu为例,讲解一下Linux安装U盘的制作方法。

首先,下载安装盘的ISO镜像。
http://releases.ubuntu.com/

然后要知道,自己的BIOS模式是什么,是Legecy还是UEFI。这个通过查看操作系统信息或BIOS设置就可以知道。

如果是Legecy模式:
1、下载工具universal usb installer
2、制作安装U盘。
3、重启,从U盘启动即可

如果是UEFI模式:
1、那只需要将盘格式化为FAT32模式,然后将64位的ISO镜像解压到盘的根目录就好了。
2、保证在盘的根目录可以开单到UEFI目录。
3、重启,关闭BIOS中的安全启动保护,从而可以用U盘启动
4、重启,从U盘启动即可
5、安装后,记得打开BIOS中安全安全启动保护

Oracle数据泵导入导出

首先要说明一下,数据泵只可以在服务端运行,而且数据泵要用到DIRECTORY对象。

一、新建DIRECTORY并授权

#创建DIRECTORY
CREATE DIRECTORY dump_dir AS 'DIRECTORY_FULL_PATH';

#授权
GRANT READ, WRITE ON DIRECTORY dump_dir TO user_id;

二、数据泵导出数据

#导出表
expdp user_id/user_pwd directory=dump_dir dumpfile=table01.dmp tables=table01 logfile=table01.log

#导出方案
expdp user_id/user_pwd directory=dump_dir dumpfile=schema01.dmp schemas=schema01 logfile=schema01.log

#导出表空间
expdp user_id/user_pwd directory=dump_dir dumpfile=tbs01.dmp tablespaces=tbs01 logfile=tbs01.log

#导出数据库
expdp user_id/user_pwd directory=dump_dir dumpfile=db01.dmp full=y logfile=db01.log

三、数据泵导入数据

#导入表
impdp user_id/user_pwd directory=dump_dir dumpfile=table01.dmp tables=table01 

#导入方案
impdp user_id/user_pwd directory=dump_dir dumpfile=schema01.dmp schemas=schema01

#导入表空间
impdp user_id/user_pwd directory=dump_dir dumpfile=tbs01.dmp tablespaces=tbs01

#导入数据库
impdp user_id/user_pwd directory=dump_dir dumpfile=db01.dmp full=y

Windows创建符号连接

1、mklink
该命令可以创建符号链接、硬链接及快捷方式。

MKLINK [[/D] | [/H] | [/J]] Link Target

        /D      Creates a directory symbolic link.  Default is a file
                symbolic link.
        /H      Creates a hard link instead of a symbolic link.
        /J      Creates a Directory Junction.
        Link    specifies the new symbolic link name.
        Target  specifies the path (relative or absolute) that the new link
                refers to.

2、fsutil hardlink
该命令可以创建硬链接。

create          Create a hardlink
list            Enumerate hardlinks on a file

3、junction
该工具是SYSINTERNALS提供的,可以新增或删除符号链接。

The first usage is for displaying reparse point information, the
second usage is for creating a junction point, and the last for
deleting a junction point:
usage: junction.exe [-s] [-q] <file or directory>
       -q     Don't print error messages (quiet)
       -s     Recurse subdirectories

usage: junction.exe <junction directory> <junction target>
       example: junction d:\link c:\windows

usage: junction.exe -d <junction directory>

JMX获取Tomcat管理信息

1、首先配置JVM
JVM要放到NTFS卷中,在JVM路径下找到jmxremote.access及jmxremote.password.template两个文件。
将jmxremote.password.template复制一份为jmxremote.password,对运行用户可读,对普通用户不可读。

2、配置Tomcat启动参数
修改catalina.bat,增加下面一行

SET "JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=8686 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true"

3、启动Tomcat

4、客户端程序JMXInfo.java

package com.neohope.jmx.test;

import java.io.IOException;
import java.lang.management.MemoryUsage;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JMXInfo {
	public static void main(String[] args) throws Exception {
		JMXConnector connector = null;
		try {
			// 获取JMX连接
			String ip = "127.0.0.1";
			String port = "8686";
			JMXServiceURL serviceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi");
			Map<String, String[]> map = new HashMap<String, String[]>();
			String[] credentials = new String[] { "controlRole", "R&D" };
			map.put("jmx.remote.credentials", credentials);
			connector = JMXConnectorFactory.connect(serviceURL, map);
			MBeanServerConnection mbsc = connector.getMBeanServerConnection();

			// 获取JVM信息
			ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");
			System.out.println("厂商:" + (String) mbsc.getAttribute(runtimeObjName, "VmVendor"));
			System.out.println("程序:" + (String) mbsc.getAttribute(runtimeObjName, "VmName"));
			System.out.println("版本:" + (String) mbsc.getAttribute(runtimeObjName, "VmVersion"));
			
			// 获取JVM运行时间
			Date starttime = new Date((Long) mbsc.getAttribute(runtimeObjName, "StartTime"));
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			System.out.println("启动时间:" + df.format(starttime));
			Long timespan = (Long) mbsc.getAttribute(runtimeObjName, "Uptime");
			System.out.println("持续工作时间:" + JMXInfo.formatTimeSpan(timespan));

			// 获取JVM内存信息
			ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
			MemoryUsage heapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName, "HeapMemoryUsage"));
			long heapMaxMemory = heapMemoryUsage.getMax();
			long heapCommitMemory = heapMemoryUsage.getCommitted();
			long heapUsedMemory = heapMemoryUsage.getUsed();
			System.out.println("heap:" + (double) heapUsedMemory * 100 / heapCommitMemory + "%");

			MemoryUsage nonheapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName, "NonHeapMemoryUsage"));
			long nonHeapCommitMemory = nonheapMemoryUsage.getCommitted();
			long nonHeapUsedMemory = heapMemoryUsage.getUsed();
			System.out.println("nonheap:" + (double) nonHeapUsedMemory * 100 / nonHeapCommitMemory + "%");

			ObjectName permObjName = new ObjectName("java.lang:type=MemoryPool,name=Perm Gen");
			MemoryUsage permGenUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(permObjName, "Usage"));
			long permCommitted = permGenUsage.getCommitted();
			long permUsed = heapMemoryUsage.getUsed();
			System.out.println("perm gen:" + (double) permUsed * 100 / permCommitted + "%");
			
			// All Domains
			for (int j = 0; j < mbsc.getDomains().length; j++) {
				System.out.println(mbsc.getDomains()[j]);
			}
			
			// All MBeans
			Set<ObjectInstance> MBeanset = mbsc.queryMBeans(null, null);
			System.out.println("MBeanset.size() : " + MBeanset.size());
			Iterator<ObjectInstance> MBeansetIterator = MBeanset.iterator();
			while (MBeansetIterator.hasNext()) {
				ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator.next();
				ObjectName objectName = objectInstance.getObjectName();
				String canonicalName = objectName.getCanonicalName();
				System.out.println("canonicalName : " + canonicalName);
			}
			
			// 全部线程池
			ObjectName threadpoolObjName = new ObjectName("Catalina:type=ThreadPool,*");
			Set<ObjectName> s2 = mbsc.queryNames(threadpoolObjName, null);
			for (ObjectName obj : s2) {
				System.out.println("端口名:" + obj.getKeyProperty("name"));
				ObjectName objname = new ObjectName(obj.getCanonicalName());
				System.out.println("最大线程数:" + mbsc.getAttribute(objname, "maxThreads"));
				System.out.println("当前线程数:" + mbsc.getAttribute(objname, "currentThreadCount"));
				System.out.println("繁忙线程数:" + mbsc.getAttribute(objname, "currentThreadsBusy"));
			}
			
			//HTTP Thread Pool
			ObjectName threadPoolObjName = new ObjectName("Catalina:type=ThreadPool,*");
			Set<ObjectName> threadPoolObjNames = mbsc.queryNames(threadPoolObjName, null);
			for (ObjectName obj : threadPoolObjNames) {
				if (obj.getKeyProperty("name").contains("http")) {
					ObjectName objname = new ObjectName(obj.getCanonicalName());
					System.out.println("HTTP最大线程数:"+ mbsc.getAttribute(objname, "maxThreads").toString());// 最大线程数
					System.out.println("HTTP当前线程数:"+ mbsc.getAttribute(objname, "currentThreadCount").toString());// 当前线程数
					System.out.println("HTTP繁忙线程数:" + mbsc.getAttribute(objname, "currentThreadsBusy").toString());// 繁忙线程数
				}
			}

			// 全部应用
			ObjectName managerObjName = new ObjectName("Catalina:type=Manager,*");
			Set<ObjectName> s = mbsc.queryNames(managerObjName, null);
			for (ObjectName obj : s) {
				System.out.println("应用名:" + obj.getKeyProperty("path"));
				ObjectName objname = new ObjectName(obj.getCanonicalName());
				System.out.println("最大会话数:" + mbsc.getAttribute(objname, "maxActiveSessions"));
				System.out.println("会话数:" + mbsc.getAttribute(objname, "activeSessions"));
				System.out.println("活动会话数:" + mbsc.getAttribute(objname, "sessionCounter"));
			}
			
			
			//RequestProcessor
			ObjectName requestObjName = new ObjectName("Catalina:type=RequestProcessor,*");
			Set<ObjectName> requestObjNameSet = mbsc.queryNames(requestObjName, null);
			Integer aliveSocketsCount = 0;
			Long maxProcessingTime = 0L;
			Long processingTime = 0L;
			Long requstCount = 0L;
			Long errorCount = 0L;
			BigDecimal bytesReceived = BigDecimal.ZERO;
			BigDecimal bytesSend = BigDecimal.ZERO;
			for (ObjectName obj : requestObjNameSet) {
				if (mbsc.getAttribute(obj, "stage").toString().trim().equals("1"))
					aliveSocketsCount++;
				long nowMaxProcessingTime = Long.parseLong(mbsc.getAttribute(obj, "maxTime").toString());
				if (maxProcessingTime < nowMaxProcessingTime)
					maxProcessingTime = nowMaxProcessingTime;
				processingTime += Long.parseLong(mbsc.getAttribute(obj, "processingTime").toString());
				requstCount += Long.parseLong(mbsc.getAttribute(obj, "requestCount").toString());
				errorCount += Long.parseLong(mbsc.getAttribute(obj, "errorCount").toString());
				bytesReceived = bytesReceived.add(new BigDecimal(mbsc.getAttribute(obj, "bytesReceived").toString()));
				bytesSend = bytesSend.add(new BigDecimal(mbsc.getAttribute(obj, "bytesSent").toString()));
			}
			System.out.println("活动sockets计数:"+ aliveSocketsCount.toString());
			System.out.println("最大处理时间:"+ maxProcessingTime.toString());
			processingTime = processingTime / 1000;
			System.out.println("总处理时间:"+ processingTime.toString());
			System.out.println("请求总数:"+ requstCount.toString());
			System.out.println("错误总数:"+ errorCount.toString());
			System.out.println("接收字节数:"+ bytesReceived.divide(new BigDecimal(1024L * 1024))
					.setScale(2, RoundingMode.HALF_UP).toPlainString());
			System.out.println("发送字节数:"+
					bytesSend.divide(new BigDecimal(1024L * 1024)).setScale(2, RoundingMode.HALF_UP).toPlainString());

		} catch (Exception e) {
			e.printStackTrace();
		}
		finally
		{
			if(connector!=null)
			{
				try {
					connector.close();
				} catch (IOException e) {
				}
			}
		}
		
	}

	public static String formatTimeSpan(long span) {
		long minseconds = span % 1000;

		span = span / 1000;
		long seconds = span % 60;

		span = span / 60;
		long mins = span % 60;

		span = span / 60;
		long hours = span % 24;

		span = span / 24;
		long days = span;
		return (new Formatter()).format("%1$d天 %2$02d小时%3$02d分%4$02d秒%5$03d毫秒", days, hours, mins, seconds, minseconds)
				.toString();
	}
}

5.运行结果

厂商:Oracle Corporation
程序:Java HotSpot(TM) Client VM
版本:24.65-b04
启动时间:2016-06-21 20:57:37
持续工作时间:0天 00小时29分31秒018毫秒
heap:60.11998789417739%
nonheap:54.523986450299915%
perm gen:165.7018025716146%
Users
JMImplementation
com.sun.management
Catalina
java.nio
java.lang
java.util.logging
MBeanset.size() : 150
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=HTMLManager
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=Manager
canonicalName : java.lang:type=Memory
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=stock
canonicalName : JMImplementation:type=MBeanServerDelegate
canonicalName : Catalina:context=/host-manager,host=localhost,name=StandardContextValve,type=Valve
canonicalName : Catalina:port=8080,type=Connector
canonicalName : Catalina:context=/examples,host=localhost,name=foo/name1,resourcetype=Context,type=Environment
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Filter,name=Tomcat WebSocket (JSR356) Filter
canonicalName : Catalina:context=/host-manager,host=localhost,type=WebappClassLoader
canonicalName : java.nio:name=mapped,type=BufferPool
canonicalName : java.lang:name=MarkSweepCompact,type=GarbageCollector
canonicalName : Catalina:context=/manager,host=localhost,name=StandardContextValve,type=Valve
canonicalName : Catalina:context=/examples,host=localhost,name=name3,resourcetype=Context,type=Environment
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,j2eeType=Filter,name=Tomcat WebSocket (JSR356) Filter
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=default
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,j2eeType=Servlet,name=jsp
canonicalName : Catalina:host=localhost,name=ErrorReportValve,type=Valve
canonicalName : Catalina:context=/host-manager,host=localhost,type=Cache
canonicalName : java.lang:name=Tenured Gen,type=MemoryPool
canonicalName : Catalina:context=/manager,host=localhost,name=BasicAuthenticator,type=Valve
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Filter,name=Tomcat WebSocket (JSR356) Filter
canonicalName : Catalina:type=Engine
canonicalName : Catalina:context=/,host=localhost,type=Manager
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=JMXProxy
canonicalName : Catalina:context=/docs,host=localhost,type=WebappClassLoader
canonicalName : java.lang:name=Code Cache,type=MemoryPool
canonicalName : java.util.logging:type=Logging
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,name=jsp,type=JspMonitor
canonicalName : Catalina:realmPath=/realm0/realm0,type=Realm
canonicalName : Catalina:name=StandardEngineValve,type=Valve
canonicalName : Catalina:port=8009,type=ProtocolHandler
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=RequestParamExample
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,j2eeType=WebModule,name=//localhost/
canonicalName : Catalina:context=/manager,host=localhost,type=Manager
canonicalName : Catalina:context=/host-manager,host=localhost,name=BasicAuthenticator,type=Valve
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Filter,name=Set Character Encoding
canonicalName : Catalina:context=/,host=localhost,type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Filter,name=Request Dumper Filter
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=ServletToJsp
canonicalName : Catalina:name=HttpRequest1,type=RequestProcessor,worker="http-apr-8080"
canonicalName : java.lang:type=Compilation
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Filter,name=SetCharacterEncoding
canonicalName : java.lang:name=Survivor Space,type=MemoryPool
canonicalName : Catalina:port=8080,type=ProtocolHandler
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=ChatServlet
canonicalName : Catalina:context=/examples,host=localhost,type=WebappClassLoader
canonicalName : Catalina:context=/examples,host=localhost,name=foo/bar/name2,resourcetype=Context,type=Environment
canonicalName : Catalina:type=StringCache
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/docs,j2eeType=Filter,name=Tomcat WebSocket (JSR356) Filter
canonicalName : java.lang:type=Threading
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=Status
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,j2eeType=WebModule,name=//localhost/manager
canonicalName : Catalina:host=localhost,name=StandardHostValve,type=Valve
canonicalName : Users:database=UserDatabase,rolename=manager-gui,type=Role
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=default
canonicalName : java.lang:name=Perm Gen,type=MemoryPool
canonicalName : Catalina:port=8009,type=Mapper
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=wsEchoStream
canonicalName : Catalina:context=/docs,host=localhost,type=Loader
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Servlet,name=jsp
canonicalName : Catalina:context=/examples,host=localhost,name=FormAuthenticator,type=Valve
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=wsSnake
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Servlet,name=jsp
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Servlet,name=HostManager
canonicalName : Catalina:name="http-apr-8080",type=GlobalRequestProcessor
canonicalName : Catalina:context=/docs,host=localhost,type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=jsp
canonicalName : java.lang:name=Perm Gen [shared-rw],type=MemoryPool
canonicalName : Catalina:context=/,host=localhost,type=Cache
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=wsChat
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=CompressionFilterTestServlet
canonicalName : java.lang:name=CodeCacheManager,type=MemoryManager
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Servlet,name=HTMLHostManager
canonicalName : Catalina:host=localhost,type=Host
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/docs,j2eeType=Servlet,name=jsp
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=HelloWorldExample
canonicalName : Catalina:name=HttpRequest2,type=RequestProcessor,worker="http-apr-8080"
canonicalName : Catalina:name="ajp-apr-8009",type=GlobalRequestProcessor
canonicalName : java.lang:type=Runtime
canonicalName : java.nio:name=direct,type=BufferPool
canonicalName : java.lang:name=Copy,type=GarbageCollector
canonicalName : Catalina:name=HttpRequest3,type=RequestProcessor,worker="http-apr-8080"
canonicalName : Catalina:context=/host-manager,host=localhost,type=Manager
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,name=jsp,type=JspMonitor
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,name=jsp,type=JspMonitor
canonicalName : Catalina:host=localhost,name=AccessLogValve,type=Valve
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,j2eeType=WebModule,name=//localhost/examples
canonicalName : Catalina:name="ajp-apr-8009",type=ThreadPool
canonicalName : Catalina:type=Service
canonicalName : com.sun.management:type=HotSpotDiagnostic
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,j2eeType=Servlet,name=default
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Filter,name=Tomcat WebSocket (JSR356) Filter
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/docs,j2eeType=Servlet,name=default
canonicalName : Catalina:context=/,host=localhost,type=WebappClassLoader
canonicalName : java.lang:type=OperatingSystem
canonicalName : Catalina:context=/examples,host=localhost,name=StandardContextValve,type=Valve
canonicalName : Catalina:type=Server
canonicalName : Catalina:port=8009,type=Connector
canonicalName : Catalina:name="http-apr-8080",type=ThreadPool
canonicalName : Catalina:context=/,host=localhost,name=StandardContextValve,type=Valve
canonicalName : Catalina:class=org.apache.catalina.UserDatabase,name="UserDatabase",resourcetype=Global,type=Resource
canonicalName : Catalina:context=/manager,host=localhost,type=WebappClassLoader
canonicalName : Catalina:context=/examples,host=localhost,type=Manager
canonicalName : Catalina:context=/examples,host=localhost,type=Cache
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,j2eeType=WebModule,name=//localhost/host-manager
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,j2eeType=WebModule,name=//localhost/docs
canonicalName : Users:database=UserDatabase,type=UserDatabase
canonicalName : Catalina:context=/examples,host=localhost,name=foo/name4,resourcetype=Context,type=Environment
canonicalName : Catalina:context=/docs,host=localhost,name=StandardContextValve,type=Valve
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Filter,name=Compression Filter
canonicalName : Catalina:type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=SessionExample
canonicalName : Catalina:context=/,host=localhost,type=Loader
canonicalName : Catalina:name=common,type=ServerClassLoader
canonicalName : Catalina:context=/examples,host=localhost,type=Loader
canonicalName : Catalina:context=/manager,host=localhost,type=Cache
canonicalName : Catalina:context=/docs,host=localhost,type=Cache
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Filter,name=CSRF
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=CookieExample
canonicalName : Users:database=UserDatabase,type=User,username="tomcat"
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Filter,name=SetCharacterEncoding
canonicalName : Catalina:host=localhost,type=Deployer
canonicalName : Catalina:type=MBeanFactory
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=RequestInfoExample
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Filter,name=Timing filter
canonicalName : Catalina:context=/examples,host=localhost,type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,j2eeType=Servlet,name=default
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/manager,j2eeType=Filter,name=CSRF
canonicalName : Catalina:context=/manager,host=localhost,type=Loader
canonicalName : Users:database=UserDatabase,type=User,username="admin"
canonicalName : Catalina:context=/docs,host=localhost,type=Manager
canonicalName : java.lang:name=Eden Space,type=MemoryPool
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=RequestHeaderExample
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/docs,name=jsp,type=JspMonitor
canonicalName : java.lang:name=Perm Gen [shared-ro],type=MemoryPool
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/host-manager,name=jsp,type=JspMonitor
canonicalName : Catalina:context=/host-manager,host=localhost,type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=async2
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=async3
canonicalName : Catalina:context=/examples,host=localhost,name=minExemptions,resourcetype=Context,type=Environment
canonicalName : Catalina:context=/manager,host=localhost,type=NamingResources
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=async0
canonicalName : java.lang:type=ClassLoading
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=async1
canonicalName : Catalina:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/examples,j2eeType=Servlet,name=wsEchoMessage
canonicalName : Catalina:realmPath=/realm0,type=Realm
canonicalName : Catalina:context=/host-manager,host=localhost,type=Loader
canonicalName : Users:database=UserDatabase,rolename=tomcat,type=Role
canonicalName : Catalina:port=8080,type=Mapper
端口名:"ajp-apr-8009"
最大线程数:200
当前线程数:0
繁忙线程数:0
端口名:"http-apr-8080"
最大线程数:200
当前线程数:10
繁忙线程数:0
HTTP最大线程数:200
HTTP当前线程数:10
HTTP繁忙线程数:0
应用名:null
最大会话数:-1
会话数:0
活动会话数:0
应用名:null
最大会话数:-1
会话数:0
活动会话数:0
应用名:null
最大会话数:-1
会话数:0
活动会话数:0
应用名:null
最大会话数:-1
会话数:0
活动会话数:0
应用名:null
最大会话数:-1
会话数:0
活动会话数:0
活动sockets计数:0
最大处理时间:176
总处理时间:0
请求总数:9
错误总数:0
接收字节数:0.00
发送字节数:0.07

COM+服务授权配置

远程调用COM+时经常会遇到下面的错误:

Error: 70
Description: Permission denied

这时就要进行授权(这个方法只能调通Win7与Win7,无法调通Win7与XP)。

首先是服务端配置:

1、首先在COM+服务端新建一个用户,比如COMPTEST,用户一定要加入组Distributed COM Users。(XP没有这个组,我用了Administrator权限依然不可以。。。)

2、在COM+服务端运行

#32位系统32位COM,64位系统64位COM
dcomcnfg
#64位系统32位COM
comexp.msc -32

3、在“服务组件-》计算机-》我的电脑”右键,属性
默认属性-》确认DCOM服务开启

4、在“服务组件-》计算机-》我的电脑-》COM+应用程序”,对应的COM+应用程序上,右键,属性
安全性-》授权,取消勾选
安全性-》安全性级别,改为Process
安全性-》将身份验证级别修改为无
安全性-》将模拟级别改为匿名
激活-》激活类型改为应用程序

5、在在“服务组件-》计算机-》我的电脑-》COM+应用程序-》对应COM+应用程序-》组件”,对应的COM+组件上,右键,属性
安全性-》授权,取消勾选

然后是客户端配置
1、在客户端,添加服务端的COMPTEST用户凭证

搞定!

PS:如果还不行的话,再设置下面的内容
1、在“服务组件-》计算机-》我的电脑”右键,属性
默认属性-》将默认身份验证基本修改为无
默认属性-》将默认模拟级别改为匿名
COM安全-》访问权限,添加Everyone及匿名用户
COM安全-》启动与激活权限,添加Everyone及匿名用户
2、然后要修改一下本地安全策略,让匿名用户与Everyone权限相同
3、然后修改本地安全策略,让DCOM可以Everyone操作

COM+简单示例(05)

本篇文章介绍了如何写一个简单的COM+客户端(CSharp)。

1、首先要导入COM组件编译时生成的TBL文件(ATL),并引用COM组件的Assembly(CS)

2、代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ATLCOMPLib;
using CSDll;

namespace CSTestComp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                testATL();
                //testCS();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }

        static void testATL()
        {
            Type justATestCOMPType = System.Type.GetTypeFromProgID("ATLCOMP.JustATestCOMP", "172.16.172.3");
            IJustATestCOMP svc = (IJustATestCOMP)System.Activator.CreateInstance(justATestCOMPType);
            int c = svc.Add(1, 2);
            System.Console.WriteLine(c);
            String retValue = svc.SayHiTo("com+");
            System.Console.WriteLine(retValue);
            System.Console.Read();
        }

        static void testCS()
        {
            Type justATestCSSvcType = System.Type.GetTypeFromProgID("CSDll.JustATestCSSvc", "172.16.172.3");
            IJustATestCSSvc svc = (IJustATestCSSvc)System.Activator.CreateInstance(justATestCSSvcType);
            int c = svc.Add(1, 2);
            System.Console.WriteLine(c);
            String retValue = svc.SayHiTo("com+");
            System.Console.WriteLine(retValue);
            System.Console.Read();
        }
    }
}

如果是本机测试(带IP),一般不会遇到权限问题

PS:
用了一晚上时间,只能调通Win7与Win7之间远程调用,无法调通Win7与XP之间远程调用(总是各种提示Access is Denied)。
如果有谁调通过,麻烦留言告诉我一下。谢谢!

COM+简单示例(04)

本篇文章介绍了如何写一个简单的COM+客户端(CPP)。

#include "stdafx.h"
#include "windows.h"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
    // COM 初始化
    ::CoInitialize(NULL);       

    // 通过 ProgID 得到 CLSID
    CLSID clsid;                
    //HRESULT hr = ::CLSIDFromProgID(L"ATLCOMP.JustATestCOMP", &clsid);
    HRESULT hr = ::CLSIDFromProgID(L"CSDll.JustATestCSSvc", &clsid);
    if(!SUCCEEDED(hr))
    {
        std::cout << "clsid not found" << std::endl;
        getchar();
        return -1;
    }

    // 由 CLSID 启动组件,并得到 IDispatch 指针
    COAUTHIDENTITY authIdentity;
    authIdentity.User = (USHORT *)L"DCOMTEST";
    authIdentity.UserLength = wcslen(L"DCOMTEST");
    //authIdentity.Domain = (USHORT *)L"Domain";
    //authIdentity.DomainLength = wcslen(L"Domain");
    authIdentity.Password = (USHORT *)L"DCOMTEST";
    authIdentity.PasswordLength = wcslen(L"DCOMTEST");
    authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

    COAUTHINFO  authInfo;
    ZeroMemory(&authInfo, sizeof(COAUTHINFO));
    authInfo.dwAuthnSvc = RPC_C_AUTHN_NONE;
    authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
    //authInfo.dwAuthnSvc = RPC_C_AUTHZ_DEFAULT;
    //authInfo.dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
    //authInfo.pwszServerPrincName = L"Domain\\MachineName";
    authInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
    authInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS;
    //authInfo.pAuthIdentityData = &authIdentity;
    //authInfo.dwCapabilities = EOAC_NONE;

    COSERVERINFO coServerInfo;
    ZeroMemory(&coServerInfo, sizeof(COSERVERINFO));
    coServerInfo.pwszName = TEXT("172.16.172.3");
    coServerInfo.pAuthInfo = NULL;
    coServerInfo.dwReserved1 = 0;
    coServerInfo.dwReserved2 = 0;
    coServerInfo.pAuthInfo = &authInfo;

    MULTI_QI mqi;
    ZeroMemory(&mqi, sizeof(MULTI_QI));
    mqi.pIID=&IID_IDispatch;
    mqi.pItf=NULL;
    mqi.hr=0;
    hr = CoCreateInstanceEx(clsid,
                            NULL,
                            CLSCTX_ALL,
                            &coServerInfo,
                            1,
                            &mqi);

    IDispatch * pDisp = (IDispatch*)mqi.pItf;

    if (!SUCCEEDED(hr))
    {
        std::cout << "IDispatch not found" << std::endl;
        DWORD d = GetLastError();
        getchar();
        return -1;
    }

    LPOLESTR pwFunNameAdd = L"Add";     // 准备取得 Add 函数的序号 DispID
    DISPID dispIDAdd;                   // 取得的序号,准备保存到这里
    hr = pDisp->GetIDsOfNames(          // 根据函数名,取得序号的函数
        IID_NULL,
        &pwFunNameAdd,                  // 函数名称的数组
        1,                              // 函数名称数组中的元素个数
        LOCALE_SYSTEM_DEFAULT,          // 使用系统默认的语言环境
        &dispIDAdd);                    // 返回值
    if (!SUCCEEDED(hr))
    {
        std::cout << "Add not found" << std::endl;
        getchar();
        return -1;
    }

    VARIANTARG vAdd[2];                             // 调用 Add(1,2) 函数所需要的参数
    vAdd[0].vt = VT_I4; vAdd[0].lVal = 2;           // 第二个参数,整数2
    vAdd[1].vt = VT_I4; vAdd[1].lVal = 1;           // 第一个参数,整数1

    DISPPARAMS dispParamsAdd = {vAdd, NULL, 2, 0 }; // 把参数包装在这个结构中
    VARIANT vResultAdd;                             // 函数返回的计算结果

    hr = pDisp->Invoke(         // 调用函数
        dispIDAdd,              // 函数由 dispID 指定
        IID_NULL,
        LOCALE_SYSTEM_DEFAULT,  // 使用系统默认的语言环境
        DISPATCH_METHOD,        // 调用的是方法,不是属性
        &dispParamsAdd,         // 参数
        &vResultAdd,            // 返回值
        NULL,                   // 不考虑异常处理
        NULL);                  // 不考虑错误处理
    if (!SUCCEEDED(hr))
    {
        std::cout << "Invoke failed" << std::endl;
        getchar();
        return -1;
    }
    std::cout << vResultAdd.lVal << std::endl;

    LPOLESTR pwFunNameSayHiTo = L"SayHiTo"; // 准备取得 SayHiTo 函数的序号 DispID
    DISPID dispIDSayHiTo;                   // 取得的序号,准备保存到这里
    hr = pDisp->GetIDsOfNames(              // 根据函数名,取得序号的函数
        IID_NULL,
        &pwFunNameSayHiTo,                  // 函数名称的数组
        1,                                  // 函数名称数组中的元素个数
        LOCALE_SYSTEM_DEFAULT,              // 使用系统默认的语言环境
        &dispIDSayHiTo);                    // 返回值
    if (!SUCCEEDED(hr))
    {
        std::cout << "SayHiTo not found" << std::endl;
        getchar();
        return -1;
    }

    VARIANTARG vSayHiTo[1];                                         // 调用 vSayHiTo("dcom") 函数所需要的参数
    vSayHiTo[0].vt = VT_BSTR;   vSayHiTo[0].bstrVal = TEXT("dcom"); // 第一个参数,字符串dcom

    DISPPARAMS dispParamsSayHiTo = { vSayHiTo, NULL, 1, 0 };        // 把参数包装在这个结构中
    VARIANT vResultSayHiTo;                                         // 函数返回的计算结果

    hr = pDisp->Invoke(         // 调用函数
        dispIDSayHiTo,          // 函数由 dispID 指定
        IID_NULL,
        LOCALE_SYSTEM_DEFAULT,  // 使用系统默认的语言环境
        DISPATCH_METHOD,        // 调用的是方法,不是属性
        &dispParamsSayHiTo,     // 参数
        &vResultSayHiTo,        // 返回值
        NULL,                   // 不考虑异常处理
        NULL);                  // 不考虑错误处理
    if (!SUCCEEDED(hr))
    {
        std::cout << "Invoke failed" << std::endl;
        getchar();
        return -1;
    }

    std::wcout << vResultSayHiTo.bstrVal << std::endl;

    pDisp->Release();       // 释放接口指针
    ::CoUninitialize();     // 释放 COM

    getchar();
    return 0;
}

如果是本机测试(带IP),一般不会遇到权限问题

PS:
用了一晚上时间,只能调通Win7与Win7之间远程调用,无法调通Win7与XP之间远程调用(总是各种提示Access is Denied)。
如果有谁调通过,麻烦留言告诉我一下。谢谢!

COM+简单示例(03)

本篇文章介绍了如何写一个简单的COM+客户端(VBS)。

1、testCOMP.vbs

'发生错误时,继续运行
On Error Resume Next

'清除错误状态
Err.Clear

Set Obj=CreateObject("CSCOMTest.JustATestCOM")

'输出错误信息
If Err.Number <> 0 Then
    WScript.Echo "Error: " & Err.Number
    WScript.Echo "Error (Hex): " & Hex(Err.Number)
    WScript.Echo "Source: " &  Err.Source
    WScript.Echo "Description: " &  Err.Description
    'Err.Clear
    '退出程序
    WScript.Quit(Err.Number)
End If

'On Error Goto 0

WScript.Echo obj.Add(1,2)
WScript.Echo obj.SayHiTo("dcom")


set obj=Nothing

2、运行

cscript testCOMP.vbs

3、如果是本机测试(带IP),一般不会遇到权限问题

PS:
用了一晚上时间,只能调通Win7与Win7之间远程调用,无法调通Win7与XP之间远程调用(总是各种提示Access is Denied)。
如果有谁调通过,麻烦留言告诉我一下。谢谢!

COM+简单示例(02)

本篇文章介绍了如何用C#写一个简单的COM+组件(Dll)。

1、新建一个C# Class Library项目“CSDll”,项目增加引用“System.EnterpriseServices”

2、项目中,新增一个接口文件IJustATestCSSvc.cs,Guid要自己生成

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace CSDll
{
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("F243B9A5-A171-49AD-AA68-47CCF6A68A2A")]
    public interface IJustATestCSSvc
    {
        int Add(int a, int b);
        String SayHiTo(String someOne);
    }
}

3、项目中,新增一个类文件JustATestCSSvc.cs,Guid要自己生成

using System;
using System.Collections.Generic;
using System.EnterpriseServices;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace CSDll
{
    
    [ComVisible(true)]
    [Guid("0C7660A9-37EC-4A39-AB0E-E936B2B24A98")]
    [ProgId("CSDll.JustATestCSSvc")]
    public class JustATestCSSvc : ServicedComponent,IJustATestCSSvc
    {

        public int Add(int a, int b)
        {
            return a + b;
        }

        public String SayHiTo(String someOne)
        {
            return "Hi " + someOne + "!";
        }
    }
}

4、项目的AssemblyInfo.cs中,增加下面几行

[assembly: ApplicationName("CSDll")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false,
AccessChecksLevel = AccessChecksLevelOption.ApplicationComponent)]

5、项目属性->Application->Assembly Infomation->Make Assembly COM-Visible->打勾

6、项目属性->Signing->Sign the assembly->打勾
项目属性->Signing->Choose a strong name key file->New

7、编译

8、注册

#这里一定要用正确版本的gacutil及RegAsm
C:\VBS\DNFW4\gacutil.exe /i CSCOMTest.dll
C:\VBS\DNFW4\RegAsm.exe CSCOMTest.dll
C:\VBS\DNFW4\RegSvcs.exe /c CSCOMTest.dll

9、反注册

#这里一定要用正确版本的gacutil及RegAsm
C:\VBS\DNFW4\gacutil.exe /u CSCOMTest
C:\VBS\DNFW4\RegAsm.exe /u CSCOMTest.dll
C:\VBS\DNFW4\RegSvcs.exe /u CSCOMTest.dll

10、查看注册结果(COM+)

#32位系统32位COM,64位系统64位COM
dcomcnfg
#64位系统32位COM
comexp.msc -32