原文地址:http://os.51cto.com/art/201107/275252.htm
在AD域控制器集群中,主域控制器(PDC)跟踪域中所有计算机帐户的更改,每个域只有一个 PDC。备份域控制器(BDC)也将验证用户的登录信息并按 PDC 的需要提高其功能。在一个域中可以有多个 BDC。那么主域控制器(PDC)与备份域控制器(BDC)之间如何进行角色转换呢?
本文介绍了介绍了2种方法:
1、从主域控制器上转换角色;2、从域控制器抢占角色。
一、 实验环境:
域名为test.com
1、 原主域控制器
System: windows 20003 Server
FQDN: PDC.test.com
IP:192.168.50.1
Mask:255.255.255.0
DNS:192.168.50.1
2、 备份域控制器
System: windows 2003 Server
FQDN:BDC.test.com
IP: 192.168.50.2
Mask: 255.255.255.0
DNS:192.168.50.1
3、 Exchange 2003 Server
FQDN:mail.test.com
IP:192.168.50.3
Mask:255.255.255.0
DNS:192.168.50.1
也许有人会问,做备份域控制器升级要装个Exchange干什么?
其实我的目的是为了证明我的升级是否成功,因为Exchange和AD是紧密集成的,如果升级失败的话,Exchange应该就会停止工作。如果升级成功,对Exchange应该就没有影响,其实现在我们很多的生产环境中有很多这样的情况。
二、实验目的:
在主域控制器(PDC)出现故障的时候通过提升备份域控制器(BDC)为主域控制,从而不影响所有依靠AD的服务。
三、实验步骤
Ⅰ、PDC角色转换(适用于PDC与BDC均正常的情况)
1、 安装域控制器。第一台域控制器的安装我这里就不在说明了,但要注意一点的是,两台域控器都要安装DNS组件。在第一台域控制安装好后,下面开始安装第二台域控制器(BDC),首先将要提升为备份域控制的计算机的计算机名,IP地址及DNS跟据上面设置好以后,并加入到现有域,加入域后以域管理员的身份登陆,开始进行安装第二台域控制器。
2、在安装备份域控器前先看一下我们的Exchange Server工作是否正常,到Exchange Server 中建立两个用户test1和test2,并为他们分别建立一个邮箱,下面使用他们相互发送邮件进行测试。
3、 我们发现发送邮件测试成功,这证明Exchange是正常的。下面正式开始安装第二台域控制器。也是就备份域控制器(BDC)。
4、 以域管理员身份登陆要提升为备份域控制器的计算机,点【开始】->【运行】在运行里输入dcpromo打开活动目录安装向导,.点两个【下一步】, 打开.
5、 这里由于是安装第二台域控制器,所以选择【现有域的额外域控制器】,点【下一步】。
6、 这里输入你的域管理员的用户名和密码,点【下一步】。
7、 这里提示你的这台域控制将成为哪个域的额外域控制器,如果正确,点【下一步】,再连续点三个下一步,就开始安装了,安装完成大概要几分钟,你就耐心的等待吧
8、几分钟后安装完成,提示重新启动计算机,重新启动计算机,此时你的计算机已经成为了test.com域的备份域控制器了。此时在活动目录用户和计算机的域控制器里已经有两台域控制了
9、再查看一下FSMO(五种主控角色)的owner,安装Windows Server安装光盘中的Support目录下的support tools工具,然后打开提示符输入:netdom query fsmo 以输出FSMO的owner,
10、 现在五个角色的woner 都是PDC,我的就是要把这个五个角色转移到备份域控制器上,使备份域控制器成为这五个角色的owner。
11、现在登陆PDC(主域控制器),进入命令提示符窗口,在命令提示符下输入:ntdsutil 回车,再输入:roles 回车,再输入connections 回车,再输入connect to server BDC --> (备注:这里的dc-1是指服务器名称),提示绑定成功后,输入q退出。
12、 输入?回车可看到以下信息:
- Connections - 连接到一个特定域控制器
- Help - 显示这个帮助信息
- Quit - 返回到上一个菜单
- Seize domain naming master - 在已连接的服务器上覆盖域角色
- Seize infrastructure master - 在已连接的服务器上覆盖结构角色
- Seize PDC - 在已连接的服务器上覆盖 PDC 角色
- Seize RID master - 在已连接的服务器上覆盖 RID 角色
- Seize schema master - 在已连接的服务器上覆盖架构角色
- Select operation target - 选择的站点,服务器,域,角色和命名上下文
- Transfer domain naming master - 将已连接的服务器定为域命名主机
- Transfer infrastructure master - 将已连接的服务器定为结构主机
- Transfer PDC - 将已连接的服务器定为 PDC
- Transfer RID master - 将已连接的服务器定为 RID 主机
- Transfer schema master - 将已连接的服务器定为架构
13、然后分别输入:
- Transfer domain naming master 回车
- Transfer infrastructure master 回车
- Transfer PDC 回车
- Transfer RID master 回车
- Transfer schema master 回车
以上的命令在输入完成一条后都会有提示是否传送角色到新的服务器,选择YES,然后接着一条一条完成既可,完成以上按Q退出界面,
14、 这五个步骤完成以后,检查一下是否全部转移到备份域控制器上了,打开在第9步时装windows support tools,开始->程序->windows support tools->command prompt,输入netdom query fsmo,全部转移成功.现在五个角色的owner都是备份域控制器了.
15、角色转移成功以后,还要把GC也转移过去,打开活动目录站点和服务,展开site->default-first-site-name->servers,你会看到两台域控制器都在下面。展开备份域控制器,右击【NTDS Settings】点【属性】,勾上全局编录前面的勾,点确定
16、然后展开PDC,右击【NTDS Settings】点【属性】,去掉全局编录前面的勾。这样全局编录也转到备份域控制器上去了,致此主域控制器已经变成备份域控制器了。而PDC就成了备份域控制器了。
17、现在已经可以把原来的主域控制器(PDC)删除掉了,在(PDC)现在的辅助域控制器上运行dcpromo按照提示一步一步的删除它,然后将它退出域。就完成了整个升级过程。这里还有一点要注要的:升级完以后,你现在的主域控制器的IP地址是新的,而不是原来的那个IP地址了,而下面所有的客户端的DNS都是指向原来的主域控制器的,这样就会出现很多问题,包括你的Exchange 就找不到域控制器,所以我最简单的方法就是把备份域控制器(现在的主域控制器)的IP改为PDC(原来的主域控制器)的IP就好了。
18、 这些改完以后启动Exchange ,exchange不要做任何更改就可以正常工作了,但这时在exchange的日志里是有一项错误(MSExchangeAL 事件 8026 和8260)。原因为收件人更新服务配置为使用 Windows 域控制器被降级,。收件人更新服务尝试查询有关该更新, Windows无法联系域控制器。
解决办法:打开 Exchange 系统管理器。展开 " 收件人 " 容器, 然后单击 收件人更新服务。双击每个收件人更新服务, 然后再将 Windows 域控制器 设置更改为新域中 Windows 域控制器。这样设置完以后,重新启动计算机,一切正常了,发封邮件试试,一切正常。致此全部完成了。
FSMO角色介绍:
架构主机 (Schema master) -架构主机角色是林范围的角色,每个林一个。此角色用于扩展 Active Directory 林的架构或运行 adprep /domainprep 命令。
域命名主机 (Domain naming master) -域命名主机角色是林范围的角色,每个林一个。此角色用于向林中添加或从林中删除域或应用程序分区。
RID 主机 (RID master) - RID 主机角色是域范围的角色,每个域一个。此角色用于分配 RID 池,以便新的或现有的域控制器能够创建用户帐户、计算机帐户或安全组。
结构主机 (Infrastructure master) -结构主机角色是域范围的角色,每个域一个。此角色供域控制器使用,用于成功运行 adprep /forestprep 命令,以及更新跨域引用的对象的 SID 属性和可分辨名称属性。
PDC 模拟器 (PDC emulator) - PDC 模拟器角色是域范围的角色,每个域一个。将数据库更新发送到 Windows NT 备份域控制器的域控制器需要具备这个角色。此外,拥有此角色的域控制器也是某些管理工具的目标,它还可以更新用户帐户密码和计算机帐户密码。
主域控制器和备份域控制器有时候经常需要进行角色转换,希望读者能够熟练掌握这两个之间角色转换的方法。
类成员要复制,用“=”只是添加一个reference,要真正的复制成员,正好能用上序列化。
先把类成员都标记序列化,然后使用如下代码即可。
- public MyClass Clone()
- {
- MemoryStream stream = new MemoryStream();
- BinaryFormatter formatter = new BinaryFormatter();
- formatter.Serialize(stream, this);
- stream.Position = 0;
- return formatter.Deserialize(stream) as MyClass;
- }
调用时如下:
- MyClass newClass = new MyClass();
- newClass = oldClass.Clone();
即可生成一个与oldClass完全相同的newClass.
C#中的默认Directory<>不支持序列化,也就是说无法用序列化方式把数据进行XML文件操作,要序列化,须对其进行改造如下:
- /// <summary>
- /// 支持XML序列化的泛型 Dictionary
- /// </summary>
- /// <typeparam name="TKey"></typeparam>
- /// <typeparam name="TValue"></typeparam>
- [XmlRoot("SerializableDictionary")]
- public class SerializableDictionary<TKey, TValue>
- : Dictionary<TKey, TValue>, IXmlSerializable
- {
- #region 构造函数
- public SerializableDictionary()
- : base()
- {
- }
- public SerializableDictionary(IDictionary<TKey, TValue> dictionary)
- : base(dictionary)
- {
- }
- public SerializableDictionary(IEqualityComparer<TKey> comparer)
- : base(comparer)
- {
- }
- public SerializableDictionary(int capacity)
- : base(capacity)
- {
- }
- public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
- : base(capacity, comparer)
- {
- }
- protected SerializableDictionary(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- }
- #endregion
- #region IXmlSerializable Members
- public System.Xml.Schema.XmlSchema GetSchema()
- {
- return null;
- }
- /// <summary>
- /// 从对象的 XML 表示形式生成该对象
- /// </summary>
- /// <param name="reader"></param>
- public void ReadXml(System.Xml.XmlReader reader)
- {
- XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
- XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
- bool wasEmpty = reader.IsEmptyElement;
- reader.Read();
- if (wasEmpty)
- return;
- while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
- {
- reader.ReadStartElement("item");
- reader.ReadStartElement("key");
- TKey key = (TKey)keySerializer.Deserialize(reader);
- reader.ReadEndElement();
- reader.ReadStartElement("value");
- TValue value = (TValue)valueSerializer.Deserialize(reader);
- reader.ReadEndElement();
- this.Add(key, value);
- reader.ReadEndElement();
- reader.MoveToContent();
- }
- reader.ReadEndElement();
- }
- /**/
- /// <summary>
- /// 将对象转换为其 XML 表示形式
- /// </summary>
- /// <param name="writer"></param>
- public void WriteXml(System.Xml.XmlWriter writer)
- {
- XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
- XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
- foreach (TKey key in this.Keys)
- {
- writer.WriteStartElement("item");
- writer.WriteStartElement("key");
- keySerializer.Serialize(writer, key);
- writer.WriteEndElement();
- writer.WriteStartElement("value");
- TValue value = this[key];
- valueSerializer.Serialize(writer, value);
- writer.WriteEndElement();
- writer.WriteEndElement();
- }
- }
- #endregion
- }
用此类型定义的Directory<>变量,可以如下进行存取:
- public void Save(string filename)
- {
- System.IO.StreamWriter writer = new System.IO.StreamWriter(filename, false, System.Text.Encoding.UTF8);
- XmlSerializer ser = new XmlSerializer(MyClassInstanceName.GetType());
- ser.Serialize(writer, MyClassInstanceName);
- writer.Close();
- }
- public MyClassName Load(string filename)
- {
- System.IO.StreamReader reader = new System.IO.StreamReader(filename);
- XmlSerializer ser = new XmlSerializer(MyClassInstanceName.GetType());
- MyClassName result = new MyClassName ();
- result.MyClassInstanceName = (SerializableDictionary<string,int>)ser.Deserialize(reader);
- reader.Close();
- return result;
- }
把C#中的类用序列化保存/取出到XML文件,是很方便的事。
1. 要using命名空间:
- using System.Xml;
- using System.Xml.Serialization;
- using System.Runtime.Serialization;
2. 要在类前加序列化标记,包括每个被成员类,都要加上:
- [Serializable]
- [XmlRoot("UnitSystem")]
- public class UnitSystem
- {
- 。。。。
- }
3. 需要保存的类的变量,包括子类中的变量,前面加上标记:
- 。。。
- public class TUnitItem
- {
- [XmlAttribute(AttributeName = "ParaA")]
- public double A;
- [XmlAttribute(AttributeName = "ParaB")]
- public double B;
- 。。。
- }
4. 如果要保存的变量,是数组形式,加上如下标记:
- [XmlArray("Units")]
- [XmlArrayItem("Unit")]
- public List<TUnitItem> Units;
5. 确保每个类,都有一个不带参数的构造方法:
- //这个实际上没用,只是为了序列化而建
- public TUnitItem()
- {
- UnitStr = "";
- A = 1;
- B = 0;
- }
- //这个才是真正用来构造类的
- public TUnitItem(string Unitstr, double a, double b = 0)
- {
- UnitStr = Unitstr;
- A = a;
- B = b;
- }
6. 然后,在你的类里,添加下面的函数用来保存、读取吧,我这里的类名是UnitSystem,改成你自己的即可:
- public void Save(string filename)
- {
- System.IO.StreamWriter writer = new System.IO.StreamWriter(filename, false, System.Text.Encoding.UTF8);
- XmlSerializer ser = new XmlSerializer(GetType());
- ser.Serialize(writer, this);
- writer.Close();
- }
- public void Load(string filename)
- {
- System.IO.StreamReader reader = new System.IO.StreamReader(filename);
- XmlSerializer ser = new XmlSerializer(typeof(dbrcomponent));
- UnitSystem result = (UnitSystem)ser.Deserialize(reader);
- reader.Close();
- return result;
- }
4年前用VS2005的C#编写了一个应用程序,用于调试VC++写的AMINE计算包。自从发布出去以后,就已经很久没有用过了。这两天有要求要重新改良一下这个软件,于是把这个程序移植到了VS2010,在Windows 7 64bit下重新编译通过,但是当运行case时,却发现出问题了。
界面每次调用DLL中的amDBRInitialize()进行初始化时,就报错。试了一下放在我的VM下的32bit的WIN7,XP下,也都会出这问题。但是在别人的windows XP下就是好的,在我另一台XP下也是好的。更奇怪的时,用以前vs2005编译的界面和DLL,也都存在同样的问题。
还好VS下抓错误信息很方便,错误为An attempt was made to load a program with an incorrect format.
查找后发现,这还是因为x86和x64兼容性的问题。因为dll是32位编译的,而编译界面时,无论以前的VS2005还是现在的VS2010,用的都是any cpu,结果在此64位计算机上,就出现了调用不谐调--64位的程序调用32位的DLL。所以,在VS2010上,把编译指令从ANY CPU改成X86就能解决问题。
修改以后,错误消失,这个问题算是解决了。但是奇怪的是,为什么之前在VM的32位的OS也一样不行呢?





