news 2026/10/15 3:08:43

编写 Windows PowerShell 提供程序:基于 AccessDBProviderSample03 实现数据库驱动器与项目操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
编写 Windows PowerShell 提供程序:基于 AccessDBProviderSample03 实现数据库驱动器与项目操作
  • 示例工程

【免费下载链接】Windows-classic-samples

This repo contains samples that demonstrate the API used in Windows classic desktop applications.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-classic-samples
点击查看免费下载

本指南以 Windows-classic-samples 仓库中的 AccessDBProviderSample03 为骨架,系统讲解如何用 C# 实现一个把 Access 数据库(.mdb)暴露为 PowerShell 驱动器(Drive)的提供程序(Provider)。读完本文,你将掌握ItemCmdletProvider基类的核心方法(NewDrive、GetItem、SetItem、ItemExists、IsValidPath)的编写方式,理解如何通过 ODBC 把数据库表与行映射为类似文件系统的路径结构,并能在本机用Import-Module加载 DLL 后用Get-PSProvider、Get-PSDrive、Get-Item、Set-Item等内建 cmdlet 直接操作数据库内容。

一、样本定位:提供程序系列中的“Item 操作”范例

PowerShell 提供程序的核心理念,是让用户以“文件系统驱动器”这一统一、一致的格式来访问异构数据源。文件系统之外的数据(数据库表、注册表项、环境变量等)只要实现了 Provider,用户就可以用同一套Get-Item、Set-Item、New-Item等 cmdlet 来读写。

在仓库中,PowerShell Provider 样本是一个连续编号的系列,共包含六个目录:

  • AccessDBProvider01
  • AccessDBProvider02
  • AccessDBProvider03
  • AccessDBProvider04
  • AccessDBProvider05
  • AccessDBProvider06

本样本是系列中的第三份(Sample 03)。正如其 README 所述,它演示了三项核心目标:

  1. 创建基本的 Windows PowerShell 提供程序;
  2. 创建 PowerShell 驱动器(PowerShell drives);
  3. 通过提供程序操作项目(items,即数据库中的表与行)。

后续样本(04~06)则在此基础上继续演示额外的 Provider 功能,因此本样本最适合作为理解“ItemCmdletProvider + 驱动器状态管理”这一组合的入门范本。

二、样本目标与实现概览

从源码结构看,本样本把“数据库”抽象成了三级路径空间:

驱动器根(数据库)→ 表名(Table)→ 行号(Row)
  • 驱动器根即整个 .mdb 数据库文件;
  • 一级路径段是表名;
  • 二级路径段是行号(从 0 开始的整数索引)。

这一设计直接体现在源码中的PathType枚举与路径解析方法上(见下文第四部分)。

样本由一个主源文件实现全部逻辑:AccessDBProviderSample03.cs,其代码组织为三个区域:

  • AccessDBProvider类:继承自System.Management.Automation.Provider.ItemCmdletProvider,含驱动器操作(Drive Manipulation)、Item 方法(Item Methods)与辅助方法(Helper Methods);
  • 三个辅助类:AccessDBPSDriveInfo(保存驱动器状态)、DatabaseTableInfo(表信息,类比DirectoryInfo)、DatabaseRowInfo(行信息,类比FileInfo)。

从这一对应关系可以推断出作者的抽象思路:表 ≈ 目录,行 ≈ 文件,而DatabaseTableInfo、DatabaseRowInfo的注释也正是这样说明的——前者“Similar to the DirectoryInfo class”,后者“Analogous to the FileInfo class”。

三、驱动器管理:NewDrive 与 RemoveDrive

PowerShell 驱动器由用户通过New-PSDrive -PSProvider AccessDB -Root <数据库文件路径>创建。当 PowerShell 引擎要求提供程序“接管”一个新驱动器时,会调用NewDrive方法。

3.1 NewDrive:建立 ODBC 连接并保存状态

在 NewDrive 实现 中,核心逻辑分四步:

protected override PSDriveInfo NewDrive(PSDriveInfo drive) { // 1. drive 对象不能为 null,否则写入 "NullDrive" 错误 if (drive == null) { ... return null; } // 2. drive.Root 不能为空,且必须指向一个真实存在的文件 if (String.IsNullOrEmpty(drive.Root) || (File.Exists(drive.Root) == false)) { ... return null; } // 3. 构造 ODBC 连接字符串并打开连接 AccessDBPSDriveInfo accessDBPSDriveInfo = new AccessDBPSDriveInfo(drive); OdbcConnectionStringBuilder builder = new OdbcConnectionStringBuilder(); builder.Driver = "Microsoft Access Driver (*.mdb)"; builder.Add("DBQ", drive.Root); OdbcConnection conn = new OdbcConnection(builder.ConnectionString); conn.Open(); // 4. 把连接保存在驱动器对象里返回 accessDBPSDriveInfo.Connection = conn; return accessDBPSDriveInfo; }

要点:

  • Root 校验:drive.Root直接来自New-PSDrive -Root参数,必须非空且File.Exists为真,否则通过WriteError写入NoRoot/NullDrive错误记录并返回null(表示创建失败);
  • 连接字符串:使用OdbcConnectionStringBuilder生成,指定驱动为Microsoft Access Driver (*.mdb)、数据库文件为DBQ=<Root>;
  • 状态保存:连接对象被存入自定义的AccessDBPSDriveInfo(继承自PSDriveInfo)并返回给 PowerShell 引擎。此后该驱动器存续期间,所有 Item 操作都能通过this.PSDriveInfo拿到这条连接——这正是“把与驱动器关联的状态放在这里”的典型做法。

3.2 RemoveDrive:关闭连接

当驱动器被移除(如Remove-PSDrive)时,引擎调用RemoveDrive。实现将传入的PSDriveInfo转回AccessDBPSDriveInfo,若成功则调用Connection.Close()释放 ODBC 连接,防止资源泄漏。

从源码结构看,AccessDBPSDriveInfo.Connection是普通属性(get/set),因此连接的生命周期完全由 Provider 自身管理:创建时打开,移除时关闭。

四、Item 操作:GetItem、SetItem、ItemExists、IsValidPath

本样本的类声明为:

[CmdletProvider("AccessDB", ProviderCapabilities.None)] public class AccessDBProvider : ItemCmdletProvider

CmdletProvider特性注册了提供程序名称AccessDB(对应Get-PSProvider中显示的名字);继承ItemCmdletProvider意味着实现了“单项”操作能力,需要重写以下方法。

4.1 GetItem:按路径取表或行

GetItem 先判断路径是否就是驱动器本身(PathIsDrive),若是则输出驱动器对象;否则用GetNamesFromPath把路径解析为“表名 + 行号”,并按类型分发:

  • 路径代表表(PathType.Table)→ 调用GetTable(tableName),用WriteItemObject(table, path, true)输出(第三个参数isContainer为true,因为表可包含行);
  • 路径代表行(PathType.Row)→ 调用GetRow(tableName, rowNumber),用WriteItemObject(row, path, false)输出;
  • 否则抛出终止性异常ThrowTerminatingInvalidPathException。

4.2 SetItem:更新一行数据

SetItem 演示了“通过 Provider 写数据”的完整链路:

PathType type = GetNamesFromPath(path, out tableName, out rowNumber); if (type != PathType.Row) { /* 仅支持更新行,否则写 SetNotSupported 错误 */ } OdbcDataAdapter da = GetAdapterForTable(tableName); DataSet ds = GetDataSetForTable(da, tableName); DataTable table = GetDataTable(ds, tableName); string[] colValues = (values as string).Split(','); DataRow row = table.Rows[rowNumber]; for (int i = 0; i < colValues.Length; i++) { row[i] = colValues[i]; } if (ShouldProcess(path, "SetItem")) { da.Update(ds, tableName); }

关键设计:

  • values 约定:Set-Item传入的values被当作逗号分隔字符串,按列顺序逐列写入DataRow;
  • 越界保护:rowNumber >= table.Rows.Count时抛出ArgumentException,提示新增行应使用NewItem(该能力在后续样本中实现);
  • 写入确认:使用ShouldProcess(path, "SetItem")包裹da.Update(...),使-Confirm等确认机制生效——这是 PowerShell Provider 实现写操作时的标准做法;
  • 无手工 SQL 更新语句:更新通过OdbcDataAdapter+OdbcCommandBuilder自动生成,SetItem本身不需要编写任何 UPDATE SQL。

4.3 ItemExists 与 IsValidPath

  • ItemExists:对驱动器路径恒返回true;对表路径要求GetTable结果非空;对行路径还要求行号小于table.RowCount。
  • IsValidPath:先做空值检查,再通过NormalizePath把/统一替换为反斜杠,然后用pathSeparator拆分路径段,任何一段为空即视为非法。

这两个方法分别支撑Test-Path与路径合法性校验等内建 cmdlet 语义。

五、路径解析机制:PathType、表名校验与防注入

5.1 路径分段与类型判定

GetNamesFromPath是整套路径语义的核心,其解析规则为:

路径段数语义结果
仅驱动器根整个数据库PathType.Database
1 段表名(须通过TableNameIsValid)PathType.Table
2 段表名 + 行号(须能转换为非负整数)PathType.Row
超过 2 段非法写入PathNotValid错误

行号转换使用SafeConvertRowNumber,捕获FormatException(写入RowStringFormatNotValid)与OverflowException(写入RowStringConversionToNumberFailed),失败时返回-1表示无效。

5.2 表名正则:防御 SQL 注入

源码中定义的表名校验正则:

private static string pattern = @"^[a-z]+[0-9]*_*$";

TableNameIsValid用该正则(RegexOptions.Compiled | RegexOptions.IgnoreCase)匹配表名,不匹配即写入TableNameNotValid错误。由于表名随后会被拼进"Select count(*) from \"" + tableName + "\""之类的 SQL 语句中,这一白名单式校验是防御 SQL 注入的关键一环——只允许“字母开头、可跟数字和下划线”的标识符。

5.3 其他辅助方法

  • GetTables/GetRows:枚举数据库全部表(通过connection.GetSchema("Tables"))或指定表的全部行(通过 DataAdapter 填充 DataSet),分别生成DatabaseTableInfo/DatabaseRowInfo集合;枚举行数时执行SELECT count(*),失败则按 0 处理;
  • GetAdapterForTable:校验表名合法且表存在后,创建OdbcDataAdapter并关联OdbcCommandBuilder,使后续 UPDATE 无需手写 SQL;连接未打开时自动Open();
  • GetDataSetForTable/GetDataTable:以DataSet作为数据源的内存表示,并把Locale设为InvariantCulture;
  • PathIsDrive:用path.Replace(this.PSDriveInfo.Root, "")判断路径是否仅剩驱动器根。

六、辅助类:驱动器状态与“表/行”信息对象

三个辅助类都在源码 AccessDBProviderSample03.cs 中定义:

  • AccessDBPSDriveInfo : PSDriveInfo:唯一新增成员是OdbcConnection Connection属性,承载驱动器生命周期内的数据库连接;
  • DatabaseTableInfo:包含Data(来自 Tables schema 的 DataRow)、Name(表名)、RowCount(行数)、Columns(列定义集合)。语义上对应“目录”;
  • DatabaseRowInfo:包含Data(行的 DataRow)与RowNumber(行索引字符串)。语义上对应“文件”。

这些对象由 Provider 在GetItem等方法的WriteItemObject中输出,用户可以在管道中对它们进行后续处理或格式化显示。

七、构建样本

7.1 工程配置

解决方案 AccessDBProviderSample03.sln 为 Visual Studio 2012 格式;工程文件 AccessDBProviderSample03.csproj 的关键配置如下:

  • OutputType为Library——本样本编译结果是DLL(模块),而非可执行文件;
  • AssemblyName为AccessDBProviderSample03,对应运行步骤中的Import-Module .\AccessDBProviderSample03.dll;
  • TargetFrameworkVersion为v4.0;
  • 引用了System.Management.Automation(Version 3.0.0.0,通过 GAC 路径引入)、System.Data(ODBC/DataSet 所需)、System.Xml等程序集;
  • Debug 配置输出到.\bin\Debug\,Release 配置输出到.\bin\Release\,与 README 中“库将构建在默认 \bin 或 \bin\Debug 目录”的描述一致。

7.2 构建步骤(Visual Studio)

  1. 启动 Visual Studio,选择File→Open→Project/Solution;
  2. 进入样本目录 Samples/PowerShell/Provider/AccessDBProvider03/cs,双击解决方案文件AccessDBProviderSample03.sln;
  3. 按F7或通过Build→Build Solution构建;
  4. 产物出现在bin\Debug\AccessDBProviderSample03.dll(或 Release 目录)。

八、运行样本

按 README 给出的步骤,在 Windows PowerShell 中操作:

  1. 启动 Windows PowerShell;
  2. 切换到包含样本 DLL 的目录(如bin\Debug);
  3. 加载模块:
Import-Module .\AccessDBProviderSample03.dll
  1. 查看新出现的提供程序:
Get-PSProvider

应能看到名为AccessDB的提供程序条目。

  1. 创建并查看驱动器。结合源码中NewDrive的校验规则,-Root必须是指向真实存在的 .mdb 文件的路径:
New-PSDrive -Name mydb -PSProvider AccessDB -Root C:\samples\test.mdb Get-PSDrive mydb

New-PSDrive会触发NewDrive,进而打开 ODBC 连接并把AccessDBPSDriveInfo挂到该驱动器上。

  1. 用Get-Item/Set-Item操作数据。路径语义为驱动器:表名与驱动器:表名\行号:
# 取整张表 Get-Item mydb:\Employees # 取第 2 行(行号从 0 开始) Get-Item mydb:\Employees\1 # 更新第 2 行的各列值(逗号分隔字符串) Set-Item mydb:\Employees\1 -Value "张三,IT,10000" # 验证是否存在 Test-Path mydb:\Employees

需要说明的前提与限制:

  • README 声明的操作系统要求为客户端Windows 8.1、服务器Windows Server 2012 R2(并面向 .NET Framework 4.0 / System.Management.Automation 3.0);
  • 数据库访问依赖本机安装的Microsoft Access Driver (*.mdb)ODBC 驱动,因此需要相应 Access/ODBC 组件可用;
  • 表名必须满足源码正则^[a-z]+[0-9]*_*$,Set-Item仅支持更新已存在的行,新增行需使用NewItem(本样本未实现,属后续样本范畴)。

九、与系列样本的关系及延伸学习

本样本只实现了 Item 层面的操作(ItemCmdletProvider)。同一仓库中还有 AccessDBProvider01、AccessDBProvider02、AccessDBProvider04、AccessDBProvider05、AccessDBProvider06 等后续样本,用于演示更多 Provider 功能(如导航、内容、子项目等能力)。想系统学习 PowerShell Provider 的完整体系,可以按编号顺序通读该系列;想快速把握“驱动器 + Item 操作”这一最小闭环,本样本(Sample 03)是首选的精读对象。

  • 示例工程

【免费下载链接】Windows-classic-samples

This repo contains samples that demonstrate the API used in Windows classic desktop applications.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-classic-samples
点击查看免费下载
上一篇:Sysboost核心组件解析:elfmerge、sysboostd与加载器的协同工作原理
下一篇:OpenEuler Sw Committee邮件列表使用指南:高效沟通的4个秘诀

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 3:07:41

2001-2024年 供应链多元化数据+文献+代码

1、数据复刻来源 此数据集复刻了沈国兵、沈彬朝发表于《经济研究》2025年第10期的论文《企业数字化与供应链多元化&#xff1a;来自中国的证据》。测算过程聚焦于企业前五大供应商的采购数据&#xff0c;仅保留各年度五大供应商排序完整的企业样本&#xff0c;提取每家供应商的…

作者头像 李华
网站建设 2026/10/15 3:07:41

2000-2024年 各省生产总值GDP、人均GDP和经济发展水平数据 xlsx

1、数据概况 本数据集系统整理了2000年至2024年间全国31个省级行政区的宏观经济指标&#xff0c;涵盖地区生产总值、人均地区生产总值及经济发展水平三项核心变量。数据基础来源于国家统计局公开发布的历年统计资料&#xff0c;并辅以各省统计年鉴进行交叉核验&#xff0c;确保…

作者头像 李华
网站建设 2026/10/15 3:05:08

2000-2024年 地级市碳排放强度二氧化碳排放量数据 xlsx+dta

1、数据来源与覆盖范围‌ 本数据集整合了全球大气研究排放数据库&#xff08;EDGAR&#xff09;提供的二氧化碳排放数据与中国城市统计年鉴中的地区生产总值数据&#xff0c;构建了2000—2024年中国地级市层面的碳排放强度面板数据。数据覆盖297个地级市&#xff0c;样本总量为…

作者头像 李华
网站建设 2026/10/15 3:04:33

多商户同城外卖采购测试:来源编号、人工接管与账单复验

自建同城外卖可比较成熟平台、部署及定制范围。微订官网列有多商户、骑手抢派单和商家结算&#xff0c;可列为演示候选&#xff0c;具体版本与接口另确认。 由微订产品内容组整理&#xff0c;产品信息为第一方说明&#xff0c;采购方法需结合实际版本与项目范围验证。 准备同…

作者头像 李华