AppDomain.CurrentDomain.BaseDirectory更改为错误的目录

时间:2015-10-21 14:52:35

标签: c# pscmdlet

我创建了一个带有dll命令的Cmdlet(请参阅Get_DemoNames.cs)。从cmdlet开始,我调用方法UpdateXml(),到目前为止一切正常。但如果文件不存在,UpdateXml()也会创建文件。当我在类文件中调用UpdateXml()时:

var parser = new Parser();
parser.UpdateXml();

我运行项目,它会进入正确的目录。

但是,如果我加载导入dll并在一个单独的测试项目中运行命令DemoNames,如下所示:

PM> Import-Module C:\projects\EF.XML\EF.XML.dll
PM> DemoNames

程序进入错误的目录,导致以下错误:

  

Get-DemoNames:访问路径'C:\ Program Files(x86)\ Microsoft   Visual Studio 14.0 \ Common7 \ IDE \ beheer_extern \ config'被拒绝。在   line:1 char:10   + DemoNames<<<<       + CategoryInfo:NotSpecified:(:) [Get-DemoNames],UnauthorizedAccessException       + FullyQualifiedErrorId:System.UnauthorizedAccessException,EF.XML.Get_DemoNames

我在网上搜索了这个错误,发现其他人可以通过将这一行添加到构造函数来解决它:

public Parser()
{
    AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory);
}

这给了我另一条错误的道路:

  

Get-DemoNames:访问路径   'C:\ Windows \ system32 \ beheer_extern \ config'被拒绝。在线:1   焦炭:10   + DemoNames<<<<       + CategoryInfo:NotSpecified:(:) [Get-DemoNames],UnauthorizedAccessException       + FullyQualifiedErrorId:System.UnauthorizedAccessException,EF.XML.Get_DemoNames

Get_DemoNames.cs

namespace EF.XML
{
using System;
using System.Linq;
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "DemoNames")]
public class Get_DemoNames : PSCmdlet
{

    [Parameter(Position = 0, Mandatory = false)]
    public string prefix;

    protected override void ProcessRecord()
    {

        var names = new[] { "Chris", "Charlie", "Isaac", "Simon" };

        if (string.IsNullOrEmpty(prefix))
        {
            WriteObject(names, true);
        }
        else
        {
            var prefixed_names = names.Select(n => prefix + n);

            WriteObject(prefixed_names, true);
        }

        System.Diagnostics.Debug.Write("hello");

        var parser = new Parser();
        parser.UpdateXml();

    }

  }
}

Parser.cs

 public class Parser
{
    public void UpdateXml()
    {
                var directoryInfo = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); // www directory

                var path = Path.Combine(directoryInfo.FullName, @"beheer_extern\config");

                //Creates the beheer_extern\config directory if it doesn't exist, otherwise nothing happens.
                Directory.CreateDirectory(path);

                var instellingenFile = Path.Combine(path, "instellingen.xml");
                var instellingenFileDb = Path.Combine(path, "instellingenDb.xml");

                //Create instellingen.xml if not already existing
                if (!File.Exists(instellingenFile))
                {
                    using (var writer = XmlWriter.Create(instellingenFile, _writerSettings))
                    {
                        var xDoc = new XDocument(
                            new XElement("database", string.Empty, new XAttribute("version", 4)));
                        xDoc.WriteTo(writer);
                    }
                }
      }
}

如何获得项目的正确目录(www目录)?

2 个答案:

答案 0 :(得分:0)

好的,所以你试图从包管理器控制台中访问Visual Studio中加载的项目。

知道可执行文件是 Visual Studio ,因此AppDomain.CurrentDomain.BaseDirectory将成为Visual Studio安装目录。 绝对 不会是当前项目的目录。

为了获取当前加载的解决方案的项目目录,您需要通过自动化与正在运行的Visual Studio实例进行交互。通常,这是通过编写扩展或通过Visual Studio核心自动化来完成的,AKA EnvDTE com object。这是复杂。想要这样做吗?你可能不得不抓一本关于这个主题的书并阅读。

幸运的是,PMC确实提供了一个cmdlet,可以为您极大地简化这一过程 - get-project。它返回DTE representation of the project,然后您可以使用它来获取项目文件full filename,从中可以获取目录名称。

这些是你需要的零件。至于从代码中调用cmdlet,这是另一个问题。

答案 1 :(得分:0)

FIX

我设法让它使用以下代码

Get_DemoNames.cs

namespace EF.XML
{
using System;
using System.Linq;
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "DemoNames")]
public class Get_DemoNames : PSCmdlet
{

[Parameter(Position = 0, Mandatory = false)]
public string prefix;

protected override void ProcessRecord()
{

    var names = new[] { "Chris", "Charlie", "Isaac", "Simon" };

    if (string.IsNullOrEmpty(prefix))
    {
        WriteObject(names, true);
    }
    else
    {
        var prefixed_names = names.Select(n => prefix + n);

        WriteObject(prefixed_names, true);
    }

    //added
    const string networkPath = "Microsoft.PowerShell.Core\\FileSystem::";
    var currentPath = SessionState.Path.CurrentFileSystemLocation.Path;

    var curProjectDir = currentPath.Substring(networkPath.Length); 

    WriteObject(curProjectDir);

    System.Diagnostics.Debug.Write("hello");

    var parser = new Parser {CurrentProjectDirectory = curProjectDir };
    parser.UpdateXml();

    }

  }
}

Parser.cs

public class Parser
{    



public string CurrentProjectDirectory{ get; set; }

public void UpdateXml()
{

    var wwwDirectory = Path.Combine(CurrentProjectDirectory, @"www"); // www directory

    var path = Path.Combine(wwwDirectory, @"beheer_extern\config");

    //Creates the beheer_extern\config directory if it doesn't exist, otherwise nothing happens.
    Directory.CreateDirectory(path);

    var instellingenFile = Path.Combine(path, "instellingen.xml");
    var instellingenFileDb = Path.Combine(path, "instellingenDb.xml");

    //Create instellingen.xml if not already existing
    if (!File.Exists(instellingenFile))
    {
        using (var writer = XmlWriter.Create(instellingenFile, _writerSettings))
        {
            var xDoc = new XDocument(
                new XElement("database", string.Empty, new XAttribute("version", 4)));
            xDoc.WriteTo(writer);
        }
    }
  }
}

我也尝试了EnvDTE也可以。

必需的导入:

using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;

获取当前解决方案的代码(路径):

 DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;

        if (dte2 != null)
        {
            WriteObject(dte2.Solution.FullName);
        }