【问题标题】:Add-Type error Meta File could not be found找不到添加类型错误元文件
【发布时间】:2009-10-29 00:01:57
【问题描述】:

我创建了一个实现 Microsoft.Data.Schema.ScriptDom 和 Microsoft.Data.Schema.ScriptDom.Sql 接口的基本 C# 类。这两个程序集是 Visual Studio 数据库版 (VSDB) 的一部分,并且是解析/脚本 API。您可以解析 SQL 文本并输出格式 SQL 脚本。有关 VSDB 程序集的更多信息,请参阅this blog post。因为它们是可再分发的,所以我已经包含了程序集和 PowerShell 脚本here

#requires -version 2

add-type -path .\Microsoft.Data.Schema.ScriptDom.dll
add-type -path .\Microsoft.Data.Schema.ScriptDom.Sql.dll

$Source = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Data.Schema.ScriptDom;
using Microsoft.Data.Schema.ScriptDom.Sql;
using System.IO;

    public class SQLParser
    {
        private IScriptFragment fragment;

        public SQLParser(SqlVersion sqlVersion, bool quotedIdentifier, string inputScript)
        {
            switch (sqlVersion)
            {
                case SqlVersion.Sql80:
                    SQLParser80 (quotedIdentifier, inputScript);
                    break;
                case SqlVersion.Sql90:
                    SQLParser90 (quotedIdentifier, inputScript);
                    break;
                case SqlVersion.Sql100:
                    SQLParser100 (quotedIdentifier, inputScript);
                    break;
            }
        }

        private void SQLParser100 (bool quotedIdentifier, string inputScript)
        {
            TSql100Parser parser = new TSql100Parser(quotedIdentifier);
            Parse(parser, inputScript);
        }

        private void SQLParser90 (bool quotedIdentifier, string inputScript)
        {
            TSql90Parser parser90 = new TSql90Parser(quotedIdentifier);
            Parse(parser90, inputScript);
        }

        private void SQLParser80 (bool quotedIdentifier, string inputScript)
        {
            TSql80Parser parser80 = new TSql80Parser(quotedIdentifier);
            Parse(parser80, inputScript);
        }

        private void Parse(TSql100Parser parser, string inputScript)
        {
            IList<ParseError> errors;

            using (StringReader sr = new StringReader(inputScript))
            {
                fragment = parser.Parse(sr, out errors);
            }

            if (errors != null && errors.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var error in errors)
                {
                    sb.AppendLine(error.Message);
                    sb.AppendLine("offset " + error.Offset.ToString());
                }
                throw new ArgumentException("InvalidSQLScript", sb.ToString());
            }
        }

        private void Parse(TSql90Parser parser, string inputScript)
        {
            IList<ParseError> errors;

            using (StringReader sr = new StringReader(inputScript))
            {
                fragment = parser.Parse(sr, out errors);
            }

            if (errors != null && errors.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var error in errors)
                {
                    sb.AppendLine(error.Message);
                    sb.AppendLine("offset " + error.Offset.ToString());
                }
                throw new ArgumentException("InvalidSQLScript", sb.ToString());
            }
        }

        private void Parse(TSql80Parser parser, string inputScript)
        {
            IList<ParseError> errors;

            using (StringReader sr = new StringReader(inputScript))
            {
                fragment = parser.Parse(sr, out errors);
            }

            if (errors != null && errors.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var error in errors)
                {
                    sb.AppendLine(error.Message);
                    sb.AppendLine("offset " + error.Offset.ToString());
                }
                throw new ArgumentException("InvalidSQLScript", sb.ToString());
            }
        }

        public IScriptFragment Fragment
        {
            get { return fragment; }
        }


    }
"@
$refs = @("Microsoft.Data.Schema.ScriptDom","Microsoft.Data.Schema.ScriptDom.Sql")
add-type -ReferencedAssemblies $refs -TypeDefinition $Source -Language CSharpVersion3 -passThru

我正在使用 PowerShell V2 add-type 创建运行时类型。我已经在 3 台不同的机器上测试了脚本。在一台机器上,脚本在其他两台机器上按预期工作,产生以下错误。两个引用的程序集都放置在与 PowerShell 脚本相同的文件夹中。关于我做错了什么有什么想法吗?

PS C:\Users\u00\bin> .\SQLParser.ps1
Add-Type : (0) : Metadata file 'Microsoft.Data.Schema.ScriptDom.dll' could not be found
(1) : using System;
At C:\Users\u00\bin\SQLParser.ps1:125 char:9
+ add-type <<<<  -ReferencedAssemblies $refs -TypeDefinition $Source -Language CSharpVersion3 -passThru
    + CategoryInfo          : InvalidData: (error CS0006: M...ld not be found:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : (0) : Metadata file 'Microsoft.Data.Schema.ScriptDom.Sql.dll' could not be found
(1) : using System;
At C:\Users\u00\bin\SQLParser.ps1:125 char:9
+ add-type <<<<  -ReferencedAssemblies $refs -TypeDefinition $Source -Language CSharpVersion3 -passThru
    + CategoryInfo          : InvalidData: (error CS0006: M...ld not be found:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : Cannot add type. There were compilation errors.
At C:\Users\u00\bin\SQLParser.ps1:125 char:9
+ add-type <<<<  -ReferencedAssemblies $refs -TypeDefinition $Source -Language CSharpVersion3 -passThru
    + CategoryInfo          : InvalidData: (:) [Add-Type], InvalidOperationException
    + FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

【问题讨论】:

标签: c# powershell


【解决方案1】:

很简单,一旦你知道了;-)

Max 的示例之所以有效,是因为这些程序集位于 GAC 中,因此可以按名称引用它们。你的程序集不是,所以它们需要被路径引用。

您也不需要顶部的 Add-Type 引用,至少对于那个脚本来说不需要——只需将最后几行更改为:

$PSScriptRoot = (Split-Path $MyInvocation.MyCommand.Path -Parent)
$refs = @("$PSScriptRoot\Microsoft.Data.Schema.ScriptDom.dll","$PSScriptRoot\Microsoft.Data.Schema.ScriptDom.Sql.dll")
add-type -ReferencedAssemblies $refs -TypeDefinition $Source -Language CSharpVersion3 -passThru

【讨论】:

    【解决方案2】:

    我有一个我在 PS 跟踪中使用过的样本。这有点基本但有效。这是使用 SMO 的代码:

    $Assem = ("Microsoft.SqlServer.Smo","Microsoft.SqlServer.ConnectionInfo")
    $Source = @"
    public class MyMSSql
    {
           public static string getEdition(string sqlName)
           {
               string sqlEdition;
               Microsoft.SqlServer.Management.Smo.Server sname = new Microsoft.SqlServer.Management.Smo.Server(sqlName);
               sqlEdition = sname.Information.Edition;
               return sqlEdition;
           }
           public string getSqlEdition(string sqlName)
           {
               string sqlEdition;
               Microsoft.SqlServer.Management.Smo.Server sname = new Microsoft.SqlServer.Management.Smo.Server(sqlName);
               sqlEdition = sname.Information.Edition;
               return sqlEdition;
           }
    
    }
    "@;
    Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source
    [MyMSSql]::getEdition("MAX-PCWIN1")
    #Developer Edition (64-bit)
    
    $MySQLobj = New-Object MyMSSql
    $MySQLobj.getSqlEdition("MAX-PCWIN1")
    

    希望这会给你一个提示。

    最大

    【讨论】:

    • 谢谢 -- 是的,当您演示时我在场,我下载了您的演示以查看一些 add-type 示例,当时我最初创建了我发布的代码。
    【解决方案3】:

    如果您将 VSTSDB 程序集放在与脚本相同的目录中,那么您不想使用“。”在相对路径中。 “。”将相对于调用脚本的目录。尝试这样的事情:

    $ScriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
    Add-Type -Path "$ScriptDir\Microsoft.Data.Schema.ScriptDom.dll"
    

    【讨论】:

    • 好建议,但我试过了。我继续并再次尝试,更改后同样的错误: $ScriptDir = Split-Path ($MyInvocation.MyCommand.Path) -Parent Add-Type -Path "$ScriptDir\Microsoft.Data.Schema.ScriptDom.dll" Add-类型 -Path "$ScriptDir\Microsoft.Data.Schema.ScriptDom.Sql.dll" 程序集在我的当前目录中: PS C:\Users\u00\bin> ls Microsoft.Data.Schema.ScriptDom* |选择名称 Name ---- Microsoft.Data.Schema.ScriptDom.dll Microsoft.Data.Schema.ScriptDom.Sql.dll 能编译代码吗?
    • 不,我没有 VS 的 Data Dude 版本。另一个想法,可能是需要另一个程序集(依赖项)导致加载失败?您可以尝试使用 fuslogvw.exe (Windows/.NET SDK) 来监控 CLR 融合加载失败。
    • 您也可以将这两个程序集加载到 ILDASM 中,查看清单以了解它们所依赖的其他程序集。
    • 好的,继续下载你的 ZIP - 它运行没有错误,并在我的 Windows 7 x64 机器上添加类型 SQLParser。
    • 在 fuslogvw 下查看这个 - 唯一加载的其他程序集是 Microsoft.PowerShell.Commands.Utility 的 Microsoft.JScript,这是 Add-Type 所在的位置。
    猜你喜欢
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 2021-05-14
    • 1970-01-01
    • 2022-10-20
    • 1970-01-01
    相关资源
    最近更新 更多