C#高级编程笔记(22至25章节)文件\注册表\权限\事务

22安全(using System.Security.Principal;)

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);//当前线程用户
var principal = WindowsPrincipal.Current as WindowsPrincipal; //window组成员
var identity = principal.Identity as WindowsIdentity; //用户,可用属性.name

24文件与注册表操作

  • FileSystemInfo 表示任何文件系统对象的基类。
  • FileInfo和File表示文件系统上的文件
  • DirectoryInfo和Directory表示文件系统上的文件夹。
  • Path这个类包含的静态成员可以用于处理路径名。
  • DriveInfo它的属性和方法提供了指定驱动器的信息。
  • System.MarshalByRefObject .NET类中用于远程操作的基对象类,允许在应用程序域之间编组数据。

属性

属性名称属性作用
CreationTime文件或文件夹创建时间
DirectoryName(仅用于文件类)包含文件夹的完整路径名
Parent(仅用于文件夹类)指定子目录的父目录
Exists文件或文件夹是否存在
Extension文件的扩展名,对于文件夹它返回空白
FullName文件或文件夹的完整路径名
LastAccessTime最后一次的访问文件或文件夹的时间
LastWriteTime最后一次修改文件或文件夹的时间
Name文件或文件夹的名称
Roct(仅用于文件夹类)路径的根部分
Length(仅用于文件类)返回文件的大小(以字节为单位)

操作方法

操作名称操作作用
Create()创建给定名称的文件夹或空文件,对于FilenInfo,该方法会返回一个流对象,经便写入文件.
Delete()删除文件或文件夹,对于文件夹,有一个可以递归的Delete选项
MoveTo()移动和/或重命名文件或文件夹
CopyTo()(只适用于FieInfo类)复制文件,注意文件夹没有复制方法.如果复制完整的目录树,需要单独复制每一个文件,创建对应于旧文件夹的新文件夹
GetDirectories()(只适用于DirectoryInfo)返回DirectoryInfo对象数组,该数组表示文件夹中包含的所有文件夹
GetFiles()(只适用于DirectoryInfo)返回FilesInfo对象数组,该数组表示文件夹中包含的所有文件.
EnumerateFiles()返回文件名的IEnumerable<string>,在返回整个列表之前,可以对列表中的项执行操作
GetFileSystemInfos()(只适用于DirectoryInfo)返回FilesInfo和DirectoryInfo对象,它把文件夹中包含的所有对象表示为一个FileSystemInfo引用数组

流数数的操作方法有Open()、OpenRead()、OpenText()、OpenWrite()、Create()、CreateText()等方法,它们都是返回流对象。

Path类

path.Combine()//合并

FileProperties示例

try
            {
                string folderPath = txtBoxInput.Text;
                DirectoryInfo theFolder = new DirectoryInfo(folderPath);//得到 一个文件夹实例
                if (theFolder.Exists)//检测存在
                {
                    DisplayFolderList(theFolder.FullName);//执行方法
                    return;//返回
                }
                FileInfo theFile = new FileInfo(folderPath); //得到一个文件实例
                if (theFile.Exists)//检测存在
                {
                    DisplayFolderList(theFile.Directory.FullName);//执行方法
                    int index = listBoxFiles.Items.IndexOf(theFile.Name);//文件属性
                    listBoxFiles.SetSelected(index, true);
                    return;//返回
                }
                throw new FileNotFoundException("没有文件或文件夹 " + "this name: " + txtBoxInput.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

读取文件

  • File.ReadAllText(路径,Encoding.ASCII)//使用ASCII打开目标文件
  • File.ReadAllBytes()//返回字节数组
  • File.ReadAllLines()//逐行语取字符串返回数组

写入文件

  • File.WriteAllText(路径,字符串);//把字符串写入路径文件

FileSteam文件流

FileStream test =new FileStream(path,fileMode,FileAccess,FileShare) //相关参数见下表(以下值可以使用'|'进行合并使用)

枚举
path路径名字符串路径
FileMode文件打开模式Append追加,Create覆盖新建,CreateNew新建(存在则报错),Open打开(没有则报错),OpenOrCreate新建与打开(没有新建并打开)Truncate清除内容打开(慎用)
FileAccess文件访问权限Read读取,ReadWrite读取写入,Write写入
FileShare文件共享方式None独占,Read允许别的程序读取,Write允许别的程序写入,ReadWrite允许别的程序读取与写入
  • FileSteam.ReadByte();//读取一个字节,返回0-255的整数,如果到达流的末尾则返回-1
  • FileSteam.Read(ByteArray,0,nBytes);//把流写入一个ByteArray的字节数组中,参数0为偏移量,nBytes为字节数(参考网络传输文件),返回值为0时表示到达了流的末尾.
  • FileSteam.WritByte();//把一个字节写入流中,没有返回值
  • FileSteam.Writ(ByteArray,0,nBytes);//把一个字节数组写入流中,参数0为数组元素索引,后面为字节数,没有返回值

FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法,但经常使用StreamReader或 StreamWriter执行这些功能。这是因为FileStream类操作的是字节和字节数组,而Stream类操作的是字符数据。这是这两种类的一个重要区别,如果你是准备读取byte数据的话,用StreamReader读取然后用 System.Text.Encoding.Default.GetBytes转化的话,如下,则可能出现数据丢失的情况,如byte数据的个数不对等。因此操作byte数据时要用FileStream.

 

StreamReader类用于读取文本文件

  • StreamReader sr =  new StreamReader(FileStream实例);//FileStream(@"d:\123.txt",filemode.open,fileAccess.read)
  • StreamReader sr =  FileInfo实例.OpenText();
StreamReader方法作用
ReadLine()读取一行
ReadToEnd()读取剩于的内容
Read()读取一个字符

StreamWriter类用于写入文本文件

  • StreamWriter sw = new StreamWriter(@"D:\123.txt",true,Encoding.ASCII);以ASCII写入
  • StreamWriter sw = new StreamWriter(FileStream实例);
  • StreamWriter sw = FileInfo实例.CreateText();

相关文件操作方法

24映射内存的文件

主要用于减少I/O的操作,让CPU直接操作储存,操作请查阅网上资料

24.6读取驱动器信息

DriveInfo [] di = DriveInfo.GetDrives(); //获取计算机驱动器数组,可以使用Froeach
DriveInfo di1 = new DriveInfo(@"C:\");//获取C:\驱动器的实例

属性TotalSize总字节大小,TotalFreeSpace可用空间字节(为帐户磁盘配额),AvailableFreeSpace可用空间字节

24.7.1从文件中读取ACL(安全权限列表System.Security.AccessControl)

string myFilePath = @"D:\123.txt";
try
{
    using (FileStream myFile = new FileStream(myFilePath, FileMode.Open, FileAccess.Read))
    {
        FileSecurity fileSec = myFile.GetAccessControl();
        foreach (FileSystemAccessRule fileRule in fileSec.GetAccessRules(true, true, typeof(NTAccount)))
        {
            Console.WriteLine("{0} {1} {2} 通道出口 {3}", myFilePath, fileRule.AccessControlType == AccessControlType.Allow ? "提供" : "拒绝", fileRule.FileSystemRights, fileRule.IdentityReference);
        }
    }
}
catch
{
    Console.WriteLine("不正确的文件路径 !");
}
/*
输出
D:\123.txt 拒绝 FullControl 通道出口 YJCN\qibobo
D:\123.txt 提供 Modify, Synchronize 通道出口 NT AUTHORITY\Authenticated Users
D:\123.txt 提供 FullControl 通道出口 NT AUTHORITY\SYSTEM
D:\123.txt 提供 FullControl 通道出口 BUILTIN\Administrators
D:\123.txt 提供 FullControl 通道出口 BUILTIN\Users
 */

24.7.1从目录中读取ACL

如上面示例相同,FileStream改为

DirectoryInfo myDir = new DirectoryInfo(mentionedDir);
if (myDir.Exists) {DirectorySecurity myDirSec = myDir.GetAccessControl();程序2};//这里可以用myDirSec.GetAccessControl()

24.7.2添加ACL信息(加权限)

try
{
    using (FileStream myFile = new FileStream(@"d:\123.txt", FileMode.Open, FileAccess.ReadWrite))
    {
        FileSecurity filesec = myFile.GetAccessControl();//取得文件的权限列表
        FileSystemAccessRule newRule = new FileSystemAccessRule(new System.Security.Principal.NTAccount(@"YJCN\liganwei"), FileSystemRights.FullControl, AccessControlType.Allow);//表示一条新的权限条目,其中YJCN\liganwei可以是域/帐户 或计算机名/帐户
        filesec.AddAccessRule(newRule);//把上面的条目添加到列表中
        File.SetAccessControl(@"d:\123.txt", filesec);//把权限列表应用到文件中
    }
}
catch(ArgumentException ex)
{
    Console.WriteLine(ex);
}

24.8注册表

HKCR文件打开方式、  HKCU用户配置、 HKLM软件信息     注:软件一般存储在HKLM\Software\<CompanyName>键中

数据类型:REG_SZ(字符串),     REG_DWORD(int类型),    REG_BINARY(字节数组)

RegistryKey hklm = Registry.LocalMachine;
RegistryKey hkSoftware = hklm.OpenSubKey("Software",true);    //true表示写入权,无法写入注册表时,应该是注册表权限问题!把当前帐号加入权限      
RegistryKey hkMine = hkSoftware.CreateSubKey("MyOwnSoftware");//在software目录下建立MyOwnSoftware目录
hkMine.SetValue("MyStringValue", "Hello World");              //在MyOwnSoftware目录建立REG_DWORD子项
hkMine.SetValue("MyIntValiue", 20);                           //在MyOwnSoftware目录建立REG_DWORD子项
//hkMine.DeleteValue();删除键值 或DeleteSubKey()

24.9 写入独立存储器(System.IO.IsolatedStorage)

创建(主要学习XML的创建)

IsolatedStorageFile storFile = IsolatedStorageFile.GetUserStoreForDomain();  //创建独立存储文件实例
IsolatedStorageFileStream storStream = new IsolatedStorageFileStream("SelfPlacingWindow.Xml", FileMode.Create, FileAccess.Write);//创建独立存储文件流
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(storStream, Encoding.UTF8); //创建XmlTextWriter对象,以构建XMl文档,
writer.Formatting = System.Xml.Formatting.Indented; //设置格式子元素缩进
writer.WriteStartDocument(); //写入版本号为1.0的XML声明
writer.WriteStartElement("Settings"); //开始标记
writer.WriteValue(12); //
writer.WriteEndElement(); //结束标记
writer.Flush();
writer.Close();
storStream.Close();
storFile.Close();

读取(主要学习XML的读取)

IsolatedStorageFile storFile1 = IsolatedStorageFile.GetUserStoreForDomain(); //创建独立存储文件实例
String[] userFiles = storFile1.GetFileNames("SelfPlacingWindow.Xml");  //获取匹配文件名的文件,如果没带参数,返回所有    
foreach (string userFile in userFiles)  
{
    if(userFile == "SelfPlacingWindow.Xml")   //找到相应文件
    {
        StreamReader storStream1 = new StreamReader(new IsolatedStorageFileStream("SelfPlacingWindow.Xml", FileMode.Open, storFile1)); //流读取文件
        System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(storStream1);    ////创建XmlTextReader对象,读取文档        
        while (reader.Read())    //读取下个节点
        {
            switch (reader.Name)  //节点限定名
            {
                case "Settings":
                    Console.WriteLine(reader.ReadString());
                    break;
                default:
                    break;
            }
        }                   
    }
}
storFile1.Close();
userFiles.Clone();

25 事务

ACID属性

  • A原子性 
  • C 一致性
  • I 隔离性
  • D 持久性

25.3 数据库和实体类

SqlConnection connection = new SqlConnection( Properties.Settings.Default.CourseManagementConnectionString);
      SqlCommand courseCommand = connection.CreateCommand(); 
      courseCommand.CommandText ="INSERT INTO Courses (Number, Title) VALUES (@Number, @Title)";
      await connection.OpenAsync();
      SqlTransaction tx = connection.BeginTransaction(); //事务开始
      try
      {
        courseCommand.Transaction = tx; //加入事务
        courseCommand.Parameters.AddWithValue("@Number", course.Number);
        courseCommand.Parameters.AddWithValue("@Title", course.Title);
        await courseCommand.ExecuteNonQueryAsync();
        tx.Commit(); //提交事务
      }
      catch (Exception ex)
      {
        Trace.WriteLine("Error: " + ex.Message);
        tx.Rollback(); //回滚事务
        throw;
      }
      finally
      {
        connection.Close();
      }

25.4传统事务

SQLConnection类  BeginTransaction()开始事务,  Commit()提交事务 Rollback() 回滚事务

25.4.2 System.EnterpriseServices 优点是自动登陆事务,要派生基类(少用)

25.5 System.Transaction

25.5.1可提交的事务

相关代码查阅书本

SqlConnection connection = new SqlConnection(Properties.Settings.Default.CourseManagementConnectionString);
      await connection.OpenAsync();
      try
      {
        if (tx != null) connection.EnlistTransaction(tx); //检测事务是否有事务实例,把sql连接装入事务
....
wait command.ExecuteNonQueryAsync();
}
var tx = new CommittableTransaction();
 try
      {       
        await db.AddStudentAsync(s1, tx);
        tx.Commit();
      }
catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
        Console.WriteLine();
        tx.Rollback();
      }

25.5.2 事务处理的升级

代码与上示例相同,

await db.AddStudentAsync(s1, tx);
await db.AddStudentAsync(s2, tx);//事务升级需要启动分布式事务协调器(DTC) 在windows服务里可以找到MS DTC

可以在设置超时时间!请查看书本

25.5.3依赖事务

static void DependentTransaction()
{
  var tx = new CommittableTransaction(); //根事务
  Utilities.DisplayTransactionInformation("TX创建根", tx.TransactionInformation);
  try
  {
    Task.Factory.StartNew(TxTask, tx.DependentClone(DependentCloneOption.BlockCommitUntilComplete)); //创建依赖事务Transaction.DependentClone 方法返回一个依赖事务,阻塞父事务
            if (Utilities.AbortTx()){throw new ApplicationException("transaction abort");}
    tx.Commit(); //尝试提交事务
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
    tx.Rollback(); //回滚事务
  }
  Utilities.DisplayTransactionInformation("TX 完成了",tx.TransactionInformation);
}
static void TxTask(object obj)
{
  var tx = obj as DependentTransaction;
  Utilities.DisplayTransactionInformation("相关事务",tx.TransactionInformation);
  Thread.Sleep(3000);
  tx.Complete();//尝试完成依赖事务
  Utilities.DisplayTransactionInformation("相关TX完成",tx.TransactionInformation);
}

25.5.4环境事务

事务完成时的事件设置调用OnTransactionCompleted方法,因为SQLConnection支持环境事务,并且会自动通过连接登记它

static async Task TransactionScopeAsync()
{
  using (var scope = new TransactionScope())
  {
    Transaction.Current.TransactionCompleted += OnTransactionCompleted; //为环境事务的TransactionCompleted完成事件加入OnTransactionCompleted方法
    Utilities.DisplayTransactionInformation("Ambient TX created", Transaction.Current.TransactionInformation);
    var s1 = new Student { FirstName = "Angela",LastName = "Nagel",Company = "Kantine M101"};
    var db = new StudentData();
    await db.AddStudentAsync(s1);
    if (!Utilities.AbortTx())
      scope.Complete();//指示范围中的所有操作都已成功完成。
      else
      Console.WriteLine("transaction will be aborted");                
  }
        // scope.Dispose();这里代表结束事务,如果没调用Complete()方法,就应该调Dispose()方法结束事务
 }
    static void OnTransactionCompleted(object sender, TransactionEventArgs e)
{
  Utilities.DisplayTransactionInformation("TX completed",e.Transaction.TransactionInformation);
}

1嵌套的作用域和环境事务

TransactionScopeOption枚举的值:

  • Required(需要的)嵌套的事务要提交后才生效          
  • Required(新的事务)二个独立的事务               
  • Suppress(取消事务)

相关连接

2多线程与环境事务

try
{
  using (var scope = new TransactionScope())
  {
    Transaction.Current.TransactionCompleted += TransactionCompleted; //完成时输出
    Utilities.DisplayTransactionInformation("Main thread TX",Transaction.Current.TransactionInformation);
    Task.Factory.StartNew(TaskMethod, Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete));//创建依赖事务,如果这里没有依赖事务选项,则因是不同的线程,所以是二个不同的事务
    scope.Complete();
  }
}
catch (TransactionAbortedException ex)
{
  Console.WriteLine("Main—Transaction was aborted, {0}",ex.Message);
}

25.6隔离级别

隔离级别脏读不可重复读幻读
ReadUncommitted (可读取修改可变数据)YYY
ReadCommitted (可读取不可修改可变数据)NYY
RepeatableRead (可读取不可修改可变数据,可添加)NNY
Serializable (可读取不可修改可变数据,不可添加)NNN
var options = new TransactionOptions
{
    IsolationLevel = IsolationLevel.ReadUncommitted,Timeout = TimeSpan.FromSeconds(90) //设置事务可读可修改可变数据,超时设置为90毫秒
};
using (var test = new TransactionScope(TransactionScopeOption.Required, options))
{
}

25.7自定义资源管理器

此节涉及"浅拷贝"与"深拷贝"的相关知识 请先查看 相关的知识点

因理解问题,以下是Transactions的所有代码注释

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Transactions;

namespace Wrox.ProCSharp.Transactions
{
    public  class Transactional<T>
    {
        private T liveValue; //实时值
        private ResourceManager<T> enlistment; //临时值
        private Transaction enlistedTransaction; //事务

        public Transactional(T value)
        {
            if (Transaction.Current == null)
            {
                this.liveValue = value;
            }
            else
            {
                this.liveValue = default(T);
                GetEnlistment().Value = value;
            }
        }

        public Transactional(): this(default(T)) { }

        /// <summary>
        /// 检测是否在环境事务中,如果有
        /// </summary>
        /// <returns></returns>
        private ResourceManager<T> GetEnlistment()
        {
            Transaction tx = Transaction.Current; //获取环境事务
            Trace.Assert(tx != null, "必须用环境事务调用");//检查条件;如果条件为 false,则输出消息并显示一个消息框,后者用于显示调用堆栈。
            if (enlistedTransaction == null)//如果没有登记事务
            {
                enlistment = new ResourceManager<T>(this, tx); //实例化内部类
                tx.EnlistVolatile(enlistment, EnlistmentOptions.None); //登记事务
                enlistedTransaction = tx; 
                return enlistment;
            }
            else if (enlistedTransaction == Transaction.Current) //查看是否是在同一线程中4
            {
                return enlistment; //返回资源管理器
            }
            else
            {
                throw new TransactionException("此类仅支持与一个事务一起使用的列表");
            }
        }


        public T Value
        {
            get { return GetValue(); }
            set { SetValue(value); }
        }
        protected virtual T GetValue()
        {
            if (Transaction.Current == null)
            {
                return liveValue;
            }
            else
            {
                return GetEnlistment().Value;
            }
        }

        protected virtual void SetValue(T value)
        {
            if (Transaction.Current == null)
            {
                liveValue = value;
            }
            else
            {
                GetEnlistment().Value = value;
            }
        }
        /// <summary>
        /// 提交事务的方法
        /// </summary>
        /// <param name="value"></param>
        /// <param name="tx"></param>
        internal void Commit(T value, Transaction tx)
        {
            liveValue = value;
            enlistedTransaction = null;
        }
        /// <summary>
        /// 回滚事务的方法
        /// </summary>
        /// <param name="tx"></param>
        internal void Rollback(Transaction tx)
        {
            enlistedTransaction = null;
        }
        internal class ResourceManager<T1> : IEnlistmentNotification //内部类,只有当前项目可以访问
        {
            private Transactional<T1> parent; //临时值()
            public T1 Value { get; set; } //实时值
            private Transaction currentTransaction;//事务

            internal ResourceManager(Transactional<T1> parent, Transaction tx)
            {
                this.parent = parent;
                Value = DeepCopy(parent.liveValue);//序列化"parent.liveValue"
                currentTransaction = tx;//事务
            }            

            static ResourceManager()
            {
                Type t = typeof(T1);//获取类型类型
                //Assert方法检查条件;如果条件为 false,则输出消息并显示一个消息框,后者用于显示调用堆栈。
                Trace.Assert(t.IsSerializable, "Type " + t.Name + " 不可串行化");//Type.IsSerializable 属性如果可序列化则为 true;否则为 false。 
            }
            /// <summary>
            /// 序列化对象到流中
            /// </summary>
            /// <param name="value">对象</param>
            /// <returns></returns>
            private static T1 DeepCopy(T1 value)
            {
                using (var stream = new MemoryStream())
                {
                    var formatter = new BinaryFormatter();//以二进制格式将对象或整个连接对象图形序列化和反序列化。
                    formatter.Serialize(stream, value);//序列化value到stream流中
                    stream.Flush();//当重写Flush方法时,将清除该流的所有缓冲区,并使得所有缓冲数据被写入到基础设备
                    stream.Seek(0, SeekOrigin.Begin);//将当前流中的位置设置为指定值。
                    return (T1)formatter.Deserialize(stream);//返回 将流反序列化为对象图形。
                }
            }
            public void Prepare(PreparingEnlistment preparingEnlistment)
            {
                preparingEnlistment.Prepared();
            }

            public void Commit(Enlistment enlistment)
            {
                parent.Commit(Value, currentTransaction);
                enlistment.Done();
            }

            public void Rollback(Enlistment enlistment)
            {
                parent.Rollback(currentTransaction);
                enlistment.Done();
            }

            public void InDoubt(Enlistment enlistment)
            {
                enlistment.Done();
            }
        }
    }


}
Transactional类
ng System;
using System.Diagnostics.Contracts;
using System.Transactions;

namespace Wrox.ProCSharp.Transactions
{
  public static class Utilities
  {
    public static bool AbortTx()
    {
      Console.Write("中止事务 (y/n)?");
      return Console.ReadLine().ToLower().Equals("y");
    }

    public static void DisplayTransactionInformation(string title, TransactionInformation ti)
    {
      if (ti == null) { throw new Exception("事务不能为空"); }
      Console.WriteLine(title);
      Console.WriteLine("创建 Time: {0:T}", ti.CreationTime);
      Console.WriteLine("状态: {0}", ti.Status);
      Console.WriteLine("本地 ID: {0}", ti.LocalIdentifier);
      Console.WriteLine("分布式 ID: {0}", ti.DistributedIdentifier);
      Console.WriteLine();
    }
  }

}
Utilities中断事务方法

以上是理解主要在于添加了接口与序列化的问题!请细心解读

25.8文件事务

因此节涉及COM的相关知识,这里不做解读!!直接拿着用吧!!在代码中加下面类

using System;
using System.Runtime.InteropServices;

namespace Wrox.ProCSharp.Transactions
{
    [ComImport]
    [Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IKernelTransaction
    {
        void GetHandle(out SafeTransactionHandle ktmHandle);
    }
}
IKernelTransaction.cs
using System;
using System.Security;
using System.Security.Permissions;
using System.Security.AccessControl;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;

namespace Wrox.ProCSharp.Transactions
{
    [SecurityCritical]
    internal static class NativeMethods
    {
        [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall,
                   CharSet = CharSet.Unicode)]
        internal static extern SafeFileHandle CreateFileTransacted(
            String lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            int dwFlagsAndAttributes,
            IntPtr hTemplateFile,
            SafeTransactionHandle txHandle,
            IntPtr miniVersion,
            IntPtr extendedParameter);

        [DllImport("Kernel32.dll", SetLastError = true)]
        [ResourceExposure(ResourceScope.Machine)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CloseHandle(IntPtr handle);

    }
}
NativeMethods.cs
using System;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;


namespace Wrox.ProCSharp.Transactions
{
  [SecurityCritical]
  internal sealed class SafeTransactionHandle : SafeHandleZeroOrMinusOneIsInvalid
  {
    private SafeTransactionHandle(): base(true) { } //安全事务句柄
    public SafeTransactionHandle(IntPtr preexistingHandle, bool ownsHandle): base(ownsHandle)
    {
      SetHandle(preexistingHandle);
    }
    [ResourceExposure(ResourceScope.Machine)]
    [ResourceConsumption(ResourceScope.Machine)]
    protected override bool ReleaseHandle()
    {
      return NativeMethods.CloseHandle(handle);
    }
  }

}
SafeTransactionHandle.cs
using System;
using System.IO;
using System.Security.Permissions;
using System.Transactions;
using Microsoft.Win32.SafeHandles;

namespace Wrox.ProCSharp.Transactions
{
  public static class TransactedFile
  {
    internal const short FILE_ATTRIBUTE_NORMAL = 0x80;
    internal const short INVALID_HANDLE_VALUE = -1;
    internal const uint GENERIC_READ = 0x80000000;
    internal const uint GENERIC_WRITE = 0x40000000;
    internal const uint CREATE_NEW = 1;
    internal const uint CREATE_ALWAYS = 2;
    internal const uint OPEN_EXISTING = 3;

    [FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
    public static FileStream GetTransactedFileStream(string fileName)
    {
      IKernelTransaction ktx = (IKernelTransaction)
            TransactionInterop.GetDtcTransaction(Transaction.Current);

      SafeTransactionHandle txHandle;
      ktx.GetHandle(out txHandle);

      SafeFileHandle fileHandle = NativeMethods.CreateFileTransacted(
            fileName, GENERIC_WRITE, 0,
            IntPtr.Zero, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
            IntPtr.Zero,
            txHandle, IntPtr.Zero, IntPtr.Zero);

      return new FileStream(fileHandle, FileAccess.Write);
    }
  }
}
TransactedFile.cs

调用方法如下:

using System;
using System.IO;
using System.Transactions;
namespace Wrox.ProCSharp.Transactions
{
  class Program
  {
    static void Main()
    {
      WriteFileSample();
    }
    static async void WriteFileSample()
    {
      using (var scope = new TransactionScope())
      {
        FileStream stream = TransactedFile.GetTransactedFileStream("sample.txt");
        var writer = new StreamWriter(stream);
        await writer.WriteLineAsync("Write a transactional file");
        writer.Close();
        if (!Utilities.AbortTx())
          scope.Complete();
      }
    }
  }
}

转载于:https://www.cnblogs.com/praybb/p/8127001.html

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值